summaryrefslogtreecommitdiff
path: root/audio/SoundWire/Samples/SdcaVad/SdcaVCodec
diff options
context:
space:
mode:
Diffstat (limited to 'audio/SoundWire/Samples/SdcaVad/SdcaVCodec')
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp286
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h84
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp262
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj364
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj.Filters21
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx146
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h34
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp1150
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp808
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp218
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h522
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp1310
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc12
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp270
-rw-r--r--audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h131
15 files changed, 5618 insertions, 0 deletions
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp
new file mode 100644
index 00000000..e7b36b1f
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.cpp
@@ -0,0 +1,286 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ CircuitHelper.cpp
+
+Abstract:
+
+ This module contains helper functions for device.cpp and render.cpp files.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "private.h"
+#include "CircuitHelper.h"
+
+#ifndef __INTELLISENSE__
+#include "CircuitHelper.tmh"
+#endif
+
+PAGED_CODE_SEG
+NTSTATUS CreateRenderCircuit(
+ _In_ PACXCIRCUIT_INIT CircuitInit,
+ _In_ UNICODE_STRING CircuitName,
+ _In_ WDFDEVICE Device,
+ _Out_ ACXCIRCUIT* Circuit
+)
+{
+
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT);
+
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(CircuitInit, &CircuitName));
+
+ //
+ // Add circuit type.
+ //
+ AcxCircuitInitSetCircuitType(CircuitInit, AcxCircuitTypeRender);
+
+ //
+ // Assign the circuit's pnp-power callbacks.
+ //
+ {
+ ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks;
+ ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks);
+ powerCallbacks.EvtAcxCircuitPowerUp = CodecR_EvtCircuitPowerUp;
+ powerCallbacks.EvtAcxCircuitPowerDown = CodecR_EvtCircuitPowerDown;
+ AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(CircuitInit, &powerCallbacks);
+ }
+
+ //
+ // Assign the circuit's composite callbacks.
+ //
+ {
+ ACX_CIRCUIT_COMPOSITE_CALLBACKS compositeCallbacks;
+ ACX_CIRCUIT_COMPOSITE_CALLBACKS_INIT(&compositeCallbacks);
+ compositeCallbacks.EvtAcxCircuitCompositeCircuitInitialize = CodecR_EvtCircuitCompositeCircuitInitialize;
+ compositeCallbacks.EvtAcxCircuitCompositeInitialize = CodecR_EvtCircuitCompositeInitialize;
+ AcxCircuitInitSetAcxCircuitCompositeCallbacks(CircuitInit, &compositeCallbacks);
+ }
+
+ //
+ // Set circuit-callbacks.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback(
+ CircuitInit,
+ CodecR_EvtCircuitRequestPreprocess,
+ (ACXCONTEXT)AcxRequestTypeAny, // dbg only
+ AcxRequestTypeAny,
+ NULL,
+ AcxItemIdNone));
+
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback(
+ CircuitInit,
+ CodecR_EvtCircuitCreateStream));
+
+ //
+ // Create the circuit.
+ //
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT);
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &CircuitInit, Circuit));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS ConnectRenderCircuitElements(
+ _In_ ULONG ElementCount,
+ _In_reads_(ElementCount) ACXELEMENT* Elements,
+ _In_ ACXCIRCUIT Circuit
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // Explicitly connect the circuit/elements. Note that driver doens't
+ // need to perform this step when circuit/elements are connected in the
+ // same order as they were added to the circuit. By default ACX connects
+ // the elements starting from the sink circuit pin and ending with the
+ // source circuit pin for both render and capture devices.
+ //
+ // circuit.pin[default_sink] -> 1st element.pin[default_in]
+ // 1st element.pin[default_out] -> 2nd element.pin[default_in]
+ // 2nd element.pin[default_out] -> circuit.pin[default_source]
+ //
+ const int numElements = 2;
+ const int numConnections = numElements + 1;
+
+ ACX_CONNECTION connections[numConnections];
+ ACX_CONNECTION_INIT(&connections[0], Circuit, Elements[ElementCount - 2]);
+ ACX_CONNECTION_INIT(&connections[1], Elements[ElementCount - 2], Elements[ElementCount - 1]);
+ ACX_CONNECTION_INIT(&connections[2], Elements[ElementCount - 1], Circuit);
+
+ //
+ // Add the connections linking circuit to elements.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(Circuit, connections, SIZEOF_ARRAY(connections)));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddBlob(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_z_ const char* Blob
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(VendorPropertiesBlock);
+ STRING vendorBlob;
+ RtlInitString(&vendorBlob, Blob);
+ WDFMEMORY vendorBlobMem;
+ RETURN_NTSTATUS_IF_FAILED(WdfMemoryCreatePreallocated(NULL, vendorBlob.Buffer, vendorBlob.MaximumLength, &vendorBlobMem));
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddBlob(ObjBag, &VendorPropertiesBlock, vendorBlobMem));
+ WdfObjectDelete(vendorBlobMem);
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddEndpointId(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UINT Value
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(EndpointId);
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(ObjBag, &EndpointId, Value));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddDataPortNumber(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UINT Value
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DECLARE_CONST_ACXOBJECTBAG_SOUNDWIRE_PROPERTY_NAME(DataPortNumber);
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(ObjBag, &DataPortNumber, Value));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddTestUI4(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UINT Value
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4);
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(ObjBag, &TestUI4, Value));
+
+ return status;
+}
+
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddCircuitId(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ GUID Guid
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, CircuitId);
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddGuid(ObjBag, &CircuitId, Guid));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddUnicodeStrings(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UNICODE_STRING FriendlyNameStr,
+ _In_ UNICODE_STRING NameStr
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(FriendlyName);
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUnicodeString(ObjBag, &FriendlyName, &FriendlyNameStr));
+
+ DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(Name);
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUnicodeString(ObjBag, &Name, &NameStr));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS AddJack(
+ _In_ WDF_OBJECT_ATTRIBUTES Attributes,
+ _In_ ACXPIN Pin,
+ _In_ ULONG ChannelMapping,
+ _In_ ULONG Color,
+ _In_ ACX_JACK_CONNECTION_TYPE ConnectionType,
+ _In_ ACX_JACK_GEO_LOCATION GeoLocation,
+ _In_ ACX_JACK_GEN_LOCATION GenLocation,
+ _In_ ACX_JACK_PORT_CONNECTION PortConnection
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ ACX_JACK_CONFIG jackCfg;
+ ACX_JACK_CONFIG_INIT(&jackCfg);
+ jackCfg.Description.ChannelMapping = ChannelMapping;
+ jackCfg.Description.Color = Color;
+ jackCfg.Description.ConnectionType = ConnectionType;
+ jackCfg.Description.GeoLocation = GeoLocation;
+ jackCfg.Description.GenLocation = GenLocation;
+ jackCfg.Description.PortConnection = PortConnection;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attributes, CODEC_JACK_CONTEXT);
+ Attributes.ParentObject = Pin;
+
+ ACXJACK jack;
+ RETURN_NTSTATUS_IF_FAILED(AcxJackCreate(Pin, &Attributes, &jackCfg, &jack));
+
+ ASSERT(jack != NULL);
+
+ PCODEC_JACK_CONTEXT jackCtx;
+ jackCtx = GetCodecJackContext(jack);
+ ASSERT(jackCtx);
+ jackCtx->Dummy = 0;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxPinAddJacks(Pin, &jack, 1));
+
+ return status;
+}
+
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h
new file mode 100644
index 00000000..c3776c1c
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/CircuitHelper.h
@@ -0,0 +1,84 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ CircuitHelper.h
+
+Abstract:
+
+ This module contains helper functions for device.cpp and render.cpp files.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+PAGED_CODE_SEG
+NTSTATUS CreateRenderCircuit(
+ _In_ PACXCIRCUIT_INIT CircuitInit,
+ _In_ UNICODE_STRING CircuitName,
+ _In_ WDFDEVICE Device,
+ _Out_ ACXCIRCUIT* Circuit
+);
+
+PAGED_CODE_SEG
+NTSTATUS ConnectRenderCircuitElements(
+ _In_ ULONG ElementCount,
+ _In_reads_(ElementCount) ACXELEMENT* Elements,
+ _In_ ACXCIRCUIT Circuit
+);
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddBlob(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_z_ const char* Blob
+);
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddEndpointId(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UINT Value
+);
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddDataPortNumber(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UINT Value
+);
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddTestUI4(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UINT Value
+);
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddCircuitId(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ GUID Guid
+);
+
+PAGED_CODE_SEG
+NTSTATUS ObjBagAddUnicodeStrings(
+ _In_ ACXOBJECTBAG ObjBag,
+ _In_ UNICODE_STRING FriendlyNameStr,
+ _In_ UNICODE_STRING NameStr
+);
+
+PAGED_CODE_SEG
+NTSTATUS AddJack(
+ _In_ WDF_OBJECT_ATTRIBUTES Attributes,
+ _In_ ACXPIN Pin,
+ _In_ ULONG ChannelMapping,
+ _In_ ULONG Color,
+ _In_ ACX_JACK_CONNECTION_TYPE ConnectionType,
+ _In_ ACX_JACK_GEO_LOCATION GeoLocation,
+ _In_ ACX_JACK_GEN_LOCATION GenLocation,
+ _In_ ACX_JACK_PORT_CONNECTION PortConnection
+);
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp
new file mode 100644
index 00000000..d56a172b
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Extension.cpp
@@ -0,0 +1,262 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Extension.cpp
+
+Abstract:
+
+ SDCA XU functions
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "private.h"
+
+#ifndef __INTELLISENSE__
+#include "Extension.tmh"
+#endif
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetJackOverride
+(
+ _In_ PVOID Context, // SDCA Context
+ _In_ BOOLEAN Override // TRUE: Override
+ // FALSE: Default SDCA behavior
+)
+{
+ PAGED_CODE();
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(Override);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+
+ devCtx = GetCodecDeviceContext(Context);
+ ASSERT(devCtx != NULL);
+
+ devCtx->SdcaXuData.bExtensionJackOVerride = Override;
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetJackSelectedMode
+(
+ _In_ PVOID Context, // SDCA Context
+ _In_ ULONG GroupEntityId, // SDCA Group Entity ID for Jack(s)
+ _In_ ULONG SelectedMode // Type of jack type overriden by XU
+)
+{
+ PAGED_CODE();
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(GroupEntityId);
+ UNREFERENCED_PARAMETER(SelectedMode);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ return status;
+}
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuPDEPowerReferenceAcquire
+(
+ _In_ PVOID Context, // SDCA Context
+ _In_ ULONG PowerDomainEntityId, // SDCA Entity ID for entity
+ _In_ SDCAXU_POWER_STATE RequiredState // Power state the PowerDomain needs to be in
+)
+{
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(PowerDomainEntityId);
+ UNREFERENCED_PARAMETER(RequiredState);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ return status;
+}
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuPDEPowerReferenceRelease
+(
+ _In_ PVOID Context, // SDCA Context
+ _In_ ULONG PowerDomainEntityId, // SDCA Entity ID for entity
+ _In_ SDCAXU_POWER_STATE ReleasedState // Power state the PowerDomain no longer needs to be in
+)
+{
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(PowerDomainEntityId);
+ UNREFERENCED_PARAMETER(ReleasedState);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ return status;
+}
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuReadDeferredAudioControls
+(
+ _In_ PVOID Context, // SDCA Context
+ _Inout_ PSDCA_AUDIO_CONTROLS Controls // Array of SDCA Audio Controls
+)
+{
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(Controls);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ return status;
+}
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuWriteDeferredAudioControls
+(
+ _In_ PVOID Context, // SDCA Context
+ _Inout_ PSDCA_AUDIO_CONTROLS Controls // Array of SDCA Audio Controls
+)
+{
+ UNREFERENCED_PARAMETER(Context);
+ UNREFERENCED_PARAMETER(Controls);
+ NTSTATUS status = STATUS_SUCCESS;
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetXUEntities
+(
+ _In_ PVOID Context,
+ _In_ ULONG NumEntities,
+ _In_reads_(NumEntities)
+ ULONG EntityIDs[]
+ )
+{
+ PAGED_CODE();
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext((WDFDEVICE)Context);
+
+ if (NumEntities)
+ {
+ PULONG pXUEntities = (PULONG)ExAllocatePool2(POOL_FLAG_NON_PAGED, sizeof(ULONG) * NumEntities, DRIVER_TAG);
+ RETURN_NTSTATUS_IF_TRUE(NULL == pXUEntities, STATUS_INSUFFICIENT_RESOURCES);
+
+ for (ULONG i = 0; i < NumEntities; i++)
+ {
+ pXUEntities[i] = EntityIDs[i];
+ }
+
+ devCtx->SdcaXuData.numXUEntities = NumEntities;
+ devCtx->SdcaXuData.XUEntities = pXUEntities;
+ }
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuRegisterForInterrupts
+(
+ _In_ PVOID Context,
+ _In_ PSDCAXU_INTERRUPT_INFO InterruptInfo
+)
+{
+ PAGED_CODE();
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext((WDFDEVICE)Context);
+
+ RETURN_NTSTATUS_IF_TRUE(InterruptInfo->Size != sizeof(SDCAXU_INTERRUPT_INFO), STATUS_INVALID_PARAMETER_1);
+
+ PSDCAXU_INTERRUPT_INFO pInterruptInfo = (PSDCAXU_INTERRUPT_INFO)ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
+ InterruptInfo->Size,
+ DRIVER_TAG);
+ RETURN_NTSTATUS_IF_TRUE(NULL == pInterruptInfo, STATUS_MEMORY_NOT_ALLOCATED);
+
+ RtlCopyMemory(pInterruptInfo, InterruptInfo, InterruptInfo->Size);
+
+ devCtx->SdcaXuData.InterruptInfo = pInterruptInfo;
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS Codec_GetSdcaXu(_In_ WDFDEVICE Device)
+{
+ PAGED_CODE();
+ NTSTATUS status = STATUS_SUCCESS;
+ PCODEC_DEVICE_CONTEXT devCtx;
+
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ RtlZeroMemory(&devCtx->SdcaXuData, sizeof(devCtx->SdcaXuData));
+
+ // Initialize Interface for requesting correct version
+ devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Size = sizeof(SDCAXU_INTERFACE_V0101);
+ devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Version = SDCAXU_INTERFACE_VERSION_0101;
+
+ //
+ // Provide SDCA Interface that XU driver can call into
+ // XU driver will copy these function addresses while
+ // handling Query Interface
+ //
+ devCtx->SdcaXuData.ExtensionInterface.EvtSetXUEntities = Codec_SdcaXuSetXUEntities;
+ devCtx->SdcaXuData.ExtensionInterface.EvtRegisterForInterrupts = Codec_SdcaXuRegisterForInterrupts;
+ devCtx->SdcaXuData.ExtensionInterface.EvtSetJackOverride = Codec_SdcaXuSetJackOverride;
+ devCtx->SdcaXuData.ExtensionInterface.EvtSetJackSelectedMode = Codec_SdcaXuSetJackSelectedMode;
+ devCtx->SdcaXuData.ExtensionInterface.EvtPDEPowerReferenceAcquire = Codec_SdcaXuPDEPowerReferenceAcquire;
+ devCtx->SdcaXuData.ExtensionInterface.EvtPDEPowerReferenceRelease = Codec_SdcaXuPDEPowerReferenceRelease;
+ devCtx->SdcaXuData.ExtensionInterface.EvtReadDeferredAudioControls = Codec_SdcaXuReadDeferredAudioControls;
+ devCtx->SdcaXuData.ExtensionInterface.EvtWriteDeferredAudioControls = Codec_SdcaXuWriteDeferredAudioControls;
+
+ status = WdfFdoQueryForInterface(
+ Device,
+ &SDCAXU_INTERFACE,
+ (PINTERFACE)&(devCtx->SdcaXuData.ExtensionInterface),
+ sizeof(SDCAXU_INTERFACE_V0101),
+ SDCAXU_INTERFACE_VERSION_0101,
+ Device
+ );
+
+ if (NT_SUCCESS(status))
+ {
+ devCtx->SdcaXuData.bSdcaXu = TRUE;
+ }
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SetSdcaXuHwConfig(_In_ WDFDEVICE Device)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+ PSDCAXU_INTERFACE_V0101 exInterface = &devCtx->SdcaXuData.ExtensionInterface;
+ PVOID exContext = devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Context;
+
+ SdcaXuAcpiBlob acpiBlob;
+ acpiBlob.NumEndpoints = 2;
+ RETURN_NTSTATUS_IF_FAILED(exInterface->EvtSetHwConfig(exContext, SdcaXuHwConfigTypeAcpiBlob, &acpiBlob, sizeof(acpiBlob)));
+
+ return status;
+}
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj
new file mode 100644
index 00000000..c855cfc0
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{98C9E1FB-3F06-4B5C-BA88-545AD0A80F94}</ProjectGuid>
+ <RootNamespace>$(MSBuildProjectName)</RootNamespace>
+ <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR>
+ <KMDF_VERSION_MINOR>31</KMDF_VERSION_MINOR>
+ <ACX_VERSION_MAJOR>1</ACX_VERSION_MAJOR>
+ <ACX_VERSION_MINOR>0</ACX_VERSION_MINOR>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
+ <SupportsPackaging>false</SupportsPackaging>
+ <RequiresPackageProject>true</RequiresPackageProject>
+ <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
+ <Platform Condition="'$(Platform)' == ''">Win32</Platform>
+ <WindowsTargetPlatformVersion>$(LatestTargetPlatformVersion)</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
+ <TargetVersion>Windows10</TargetVersion>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
+ <ConfigurationType>Driver</ConfigurationType>
+ <DriverType>KMDF</DriverType>
+ <DriverTargetPlatform>Universal</DriverTargetPlatform>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <OutDir>$(IntDir)</OutDir>
+ </PropertyGroup>
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
+ <Link>
+ <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\libcntpr.lib;wpprecorder.lib;$(DDK_LIB_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR)\acxstub.lib</AdditionalDependencies>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH);$(DDK_INC_PATH)\acx\km\$(ACX_VERSION_MAJOR).$(ACX_VERSION_MINOR);..\inc;..\common\.</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions>
+ <PreprocessorDefinitions>%(PreprocessorDefinitions);ACX_VERSION_MAJOR=1;ACX_VERSION_MINOR=0;_NEW_DELETE_OPERATORS_</PreprocessorDefinitions>
+ <WppEnabled>true</WppEnabled>
+ <WppRecorderEnabled>true</WppRecorderEnabled>
+ <WppTraceFunction>
+ </WppTraceFunction>
+ <WppScanConfigurationData>..\inc\trace_macros.h</WppScanConfigurationData>
+ <WppAdditionalOptions>-km \
+-DENABLE_WPP_RECORDER=1 \
+-DENABLE_WPP_TRACE_FILTERING_WITH_WPP_RECORDER=1 \
+-func:DoTraceLevelMessage(LEVEL,FLAGS,MSG,...) \
+-p:SDCAVCodec</WppAdditionalOptions>
+ </ClCompile>
+ <DriverSign>
+ <FileDigestAlgorithm>sha256</FileDigestAlgorithm>
+ </DriverSign>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <FilesToPackage Include="$(TargetPath)" />
+ </ItemGroup>
+ <ItemGroup>
+ <Inf Exclude="@(Inx)" Include="*.inx" />
+ <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\inc\NewDelete.h" />
+ <ClInclude Include="CircuitHelper.h" />
+ <ClInclude Include="private.h" />
+ <ClInclude Include="streamengine.h" />
+ <ClInclude Include="Trace.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="capture.cpp" />
+ <ClCompile Include="CircuitHelper.cpp" />
+ <ClCompile Include="device.cpp" />
+ <ClCompile Include="driver.cpp" />
+ <ClCompile Include="Extension.cpp" />
+ <ClCompile Include="..\common\NewDelete.cpp" />
+ <ClCompile Include="render.cpp" />
+ <ClCompile Include="streamengine.cpp" />
+ <ResourceCompile Include="resources.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj.Filters b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj.Filters
new file mode 100644
index 00000000..44bc3f92
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SDCAVCodec.vcxproj.Filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ <Filter Include="Driver Files">
+ <UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ </Filter>
+ </ItemGroup>
+</Project>
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx
new file mode 100644
index 00000000..88c9eba4
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/SdcaVCodec.inx
@@ -0,0 +1,146 @@
+;/*++
+;
+;Copyright (c) Microsoft Corporation. All rights reserved.
+;
+;Module Name:
+;
+; SDCAVCodec.INF
+;
+;--*/
+
+[Version]
+Signature="$WINDOWS NT$"
+Class=SYSTEM
+ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
+Provider=%ProviderName%
+DriverVer=06/13/2016, 1.0.0.1
+CatalogFile=SDCAVad.cat
+PnpLockdown=1
+
+[DestinationDirs]
+DefaultDestDir = 13
+
+;*****************************************
+; Audio Device Install Section
+;*****************************************
+[Manufacturer]
+%StdMfg%=Standard,NT$ARCH$.10.0...19041
+
+[Standard.NT$ARCH$.10.0...19041]
+%WdfCodecDevice.DeviceDesc%=Audio_Device, ROOT\SDCAVCodec
+
+[Audio_Device.NT]
+CopyFiles=Audio_Device.NT.Copy
+
+[Audio_Device.NT.Copy]
+SDCAVCodec.sys
+
+
+[Audio_Device.NT.HW]
+AddReg=FilterLevelReg
+
+;****************************************************
+; SDCAXu filters are installed in filter level
+; SDCAXu
+;****************************************************
+[FilterLevelReg]
+HKR,,LowerFilterLevels,%REG_MULTI_SZ%,"SDCAXu","DefaultLowerFilter"
+HKR,,LowerFilterDefaultLevel,,"DefaultLowerFilter"
+
+;-------------- Service installation
+
+[Audio_Device.NT.Services]
+AddService = SDCAVCodec, %SPSVCINST_ASSOCSERVICE%, Audio_Service_Inst
+
+[Audio_Service_Inst]
+DisplayName = %WdfCodecDevice.DeviceDesc%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %13%\SDCAVCodec.sys
+
+[SourceDisksNames]
+1 = %DiskId1%,,,""
+
+[SourceDisksFiles]
+SDCAVCodec.sys = 1,,
+
+
+[Audio_Device.NT.Wdf]
+KmdfService = SDCAVCodec, Audio_wdfsect
+[Audio_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+;
+; render interfaces: speaker
+;
+[Audio_Device.I.Speaker]
+AddReg=Audio_Device.I.Speaker.AddReg
+[Audio_Device.I.Speaker.AddReg]
+HKR,,CLSID,,%Proxy.CLSID%
+HKR,,FriendlyName,,%Audio_Device.Speaker.szPname%
+; The following lines opt-in to pull mode.
+HKR,EP\0,%PKEY_AudioEndpoint_Association%,,%KSNODETYPE_ANY%
+HKR,EP\0,%PKEY_AudioEndpoint_Supports_EventDriven_Mode%,0x00010001,0x1
+
+;
+; capture interfaces: microphone
+;
+[Audio_Device.I.Microphone]
+AddReg=Audio_Device.I.Microphone.AddReg
+[Audio_Device.I.Microphone.AddReg]
+HKR,,CLSID,,%Proxy.CLSID%
+HKR,,FriendlyName,,%Audio_Device.Microphone.szPname%
+; The following lines opt-in to pull mode.
+HKR,EP\0,%PKEY_AudioEndpoint_Association%,,%KSNODETYPE_ANY%
+HKR,EP\0,%PKEY_AudioEndpoint_Supports_EventDriven_Mode%,0x00010001,0x1
+
+;
+; PnP add interface directives for static enumerated audio endpoints.
+;
+[Audio_Device.NT.Interfaces]
+; Interfaces for render endpoint.
+AddInterface=%KSCATEGORY_AUDIO%, %KSNAME_Speaker%, Audio_Device.I.Speaker
+AddInterface=%KSCATEGORY_TOPOLOGY%, %KSNAME_Speaker%, Audio_Device.I.Speaker
+
+; Interfaces for mic capture endpoint
+AddInterface=%KSCATEGORY_AUDIO%, %KSNAME_Microphone%, Audio_Device.I.Microphone
+AddInterface=%KSCATEGORY_TOPOLOGY%, %KSNAME_Microphone%, Audio_Device.I.Microphone
+
+[Strings]
+;
+;Non-localizable
+;
+KSNAME_Speaker="Speaker0"
+KSNAME_Microphone="Microphone0"
+
+SPSVCINST_ASSOCSERVICE = 0x00000002
+ProviderName = "VS_Microsoft"
+
+Proxy.CLSID = "{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
+KSCATEGORY_AUDIO = "{6994AD04-93EF-11D0-A3CC-00A0C9223196}"
+KSCATEGORY_RENDER = "{65E8773E-8F56-11D0-A3B9-00A0C9223196}"
+KSCATEGORY_CAPTURE = "{65E8773D-8F56-11D0-A3B9-00A0C9223196}"
+KSCATEGORY_REALTIME = "{EB115FFC-10C8-4964-831D-6DCB02E6F23F}"
+KSCATEGORY_TOPOLOGY = "{DDA54A40-1E4C-11D1-A050-405705C10000}"
+
+MediaCategories="SYSTEM\CurrentControlSet\Control\MediaCategories"
+KSNODETYPE_ANY = "{00000000-0000-0000-0000-000000000000}"
+
+PKEY_AudioEndpoint_ControlPanelPageProvider = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},1"
+PKEY_AudioEndpoint_Association = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},2"
+PKEY_AudioEndpoint_Supports_EventDriven_Mode = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},7"
+PKEY_AudioEndpoint_Default_VolumeInDb = "{1DA5D803-D492-4EDD-8C23-E0C0FFEE7F0E},9"
+REG_MULTI_SZ = 0x00010000
+;
+;Localizable
+;
+StdMfg = "SDCA Virtual Codec Audio Device"
+DiskId1 = "SDCA Virtual Codec Audio Driver Installation Disk"
+WdfCodecDevice.DeviceDesc = "SDCA Virtual Codec Audio Driver"
+
+;; friendly names
+Audio_Device.Speaker.szPname="SDCA Virtual Codec Speaker"
+Audio_Device.Microphone.szPname="SDCA Virtual Codec Microphone"
+
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h
new file mode 100644
index 00000000..4b292930
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/Trace.h
@@ -0,0 +1,34 @@
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+Trace.h
+
+--*/
+
+#pragma once
+
+#include <WppRecorder.h>
+#include <evntrace.h> // For TRACE_LEVEL definitions
+
+#define WPP_TOTAL_BUFFER_SIZE (PAGE_SIZE)
+#define WPP_ERROR_PARTITION_SIZE (WPP_TOTAL_BUFFER_SIZE/4)
+
+// {C456FD64-2AC1-4A72-8280-B4163555CD03}
+#define WPP_CONTROL_GUIDS \
+WPP_DEFINE_CONTROL_GUID(DrvLogger,(c456fd64,2ac1,4a72,8280,b4163555cd03), \
+ WPP_DEFINE_BIT(FLAG_DEVICE_ALL) /* bit 0 = 0x00000001 */ \
+ WPP_DEFINE_BIT(FLAG_FUNCTION) /* bit 1 = 0x00000002 */ \
+ WPP_DEFINE_BIT(FLAG_INFO) /* bit 2 = 0x00000004 */ \
+ WPP_DEFINE_BIT(FLAG_PNP) /* bit 3 = 0x00000008 */ \
+ WPP_DEFINE_BIT(FLAG_POWER) /* bit 4 = 0x00000010 */ \
+ WPP_DEFINE_BIT(FLAG_STREAM) /* bit 5 = 0x00000020 */ \
+ WPP_DEFINE_BIT(FLAG_INIT) /* bit 6 = 0x00000040 */ \
+ WPP_DEFINE_BIT(FLAG_DDI) /* bit 7 = 0x00000080 */ \
+ WPP_DEFINE_BIT(FLAG_GENERIC) /* bit 8 = 0x00000100 */ \
+ )
+
+#include "trace_macros.h"
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp
new file mode 100644
index 00000000..df6de34c
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/capture.cpp
@@ -0,0 +1,1150 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Capture.cpp
+
+Abstract:
+
+ Contains ACX Capture factory and circuit
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "private.h"
+#include <devguid.h>
+#include "stdunk.h"
+#include <ks.h>
+#include <mmsystem.h>
+#include <ksmedia.h>
+#include "streamengine.h"
+#include "soundwirecontroller.h"
+#include "sdcastreaming.h"
+#include "CircuitHelper.h"
+
+#include "AudioFormats.h"
+
+#ifndef __INTELLISENSE__
+#include "capture.tmh"
+#endif
+
+ACX_PROPERTY_ITEM KwsProperties[] =
+{
+ {
+ &KSPROPERTYSETID_SdcaKws,
+ KSPROPERTY_SDCAKWS_DEVICE_CAPABILITY,
+ ACX_PROPERTY_ITEM_FLAG_GET,
+ &CodecC_EvtCircuitDeviceKwsCapability, // Event to call
+ NULL, // Reserved
+ 0, // ControlCb
+ sizeof(DEVICE_KWS_CAPABILITY_DESCRIPTOR) // ValueCb
+ },
+ {
+ &KSPROPERTYSETID_SdcaKws,
+ KSPROPERTY_SDCAKWS_VAD_CAPABILITY,
+ ACX_PROPERTY_ITEM_FLAG_GET,
+ &CodecC_EvtCircuitVadCapability, // Event to call
+ NULL, // Reserved
+ 0, // ControlCb
+ sizeof(VAD_DESCRIPTOR) // ValueCb
+ },
+ {
+ &KSPROPERTYSETID_SdcaKws,
+ KSPROPERTY_SDCAKWS_VAD_ENTITIES,
+ ACX_PROPERTY_ITEM_FLAG_GET,
+ &CodecC_EvtCircuitVadEntities, // Event to call
+ NULL, // Reserved
+ 0, // ControlCb
+ sizeof(VAD_ENTITIES) // ValueCb
+ },
+ {
+ &KSPROPERTYSETID_SdcaKws,
+ KSPROPERTY_SDCAKWS_ACCESS_EVENTS,
+ ACX_PROPERTY_ITEM_FLAG_SET,
+ &CodecC_EvtCircuitSetKwsAccessEvents, // Event to call
+ NULL, // Reserved
+ 0, // ControlCb
+ sizeof(SDCA_KWS_NOTIFICATIONS) // ValueCb
+ },
+ {
+ &KSPROPERTYSETID_SdcaKws,
+ KSPROPERTY_SDCAKWS_CONFIGURE_VAD_PORT,
+ ACX_PROPERTY_ITEM_FLAG_SET,
+ &CodecC_EvtCircuitConfigureVadPort, // Event to call
+ NULL, // Reserved
+ 0, // ControlCb
+ sizeof(SDCA_KWS_PREPARE_PARAMS) // ValueCb
+ },
+ {
+ &KSPROPERTYSETID_SdcaKws,
+ KSPROPERTY_SDCAKWS_CLEANUP_VAD_PORT,
+ ACX_PROPERTY_ITEM_FLAG_SET,
+ &CodecC_EvtCircuitCleanupVadPort, // Event to call
+ // No parameters - can only have one
+ },
+};
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitVadCapability(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ ACX_REQUEST_PARAMETERS params;
+ ULONG_PTR outDataCb = 0;
+ PVAD_DESCRIPTOR value;
+ ULONG valueCb;
+ ULONG_PTR minSize;
+ PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx;
+ ULONG formatCount = 0;
+
+ PAGED_CODE();
+
+ circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object);
+
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+ AcxRequestGetParameters(Request, &params);
+
+ ASSERT(params.Type == AcxRequestTypeProperty);
+ ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbGet);
+
+ value = (PVAD_DESCRIPTOR)params.Parameters.Property.Value;
+ valueCb = params.Parameters.Property.ValueCb;
+
+ //
+ // Compute min size.
+ //
+ minSize = sizeof(VAD_DESCRIPTOR);
+
+ //
+ // Sample only supports 1 format
+ //
+ formatCount = 1;
+
+ // Note the VAD_DESCRIPTOR already has room for 1, hence subtracting that here
+ minSize += (formatCount - ANYSIZE_ARRAY) * sizeof(WAVEFORMATEXTENSIBLE);
+
+ if (valueCb == 0)
+ {
+ outDataCb = minSize;
+ status = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (valueCb < minSize)
+ {
+ outDataCb = 0;
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ //
+ // Reset buffer.
+ //
+ RtlZeroMemory(value, valueCb);
+
+ // It's safe for us to use the KwsDataFormat directly in AcxDataFormatGetWaveFormatExtensible
+ // because we control it and know it will have a proper WAVEFORMATEXTENSIBLE value.
+ RtlCopyMemory(value->Format, AcxDataFormatGetWaveFormatExtensible(circuitCtx->KwsDataFormat), sizeof(WAVEFORMATEXTENSIBLE));
+
+ value->FormatCount = formatCount;
+
+ //
+ // All done.
+ //
+ outDataCb = minSize;
+ status = STATUS_SUCCESS;
+ }
+
+ WdfRequestCompleteWithInformation(Request, status, outDataCb);
+}
+
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitVadEntities(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ ACX_REQUEST_PARAMETERS params;
+ ULONG_PTR outDataCb = 0;
+ PVAD_DESCRIPTOR value;
+ ULONG valueCb;
+ ULONG_PTR minSize;
+ PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx;
+
+ PAGED_CODE();
+
+ circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object);
+
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+ AcxRequestGetParameters(Request, &params);
+
+ ASSERT(params.Type == AcxRequestTypeProperty);
+ ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbGet);
+
+ value = (PVAD_DESCRIPTOR)params.Parameters.Property.Value;
+ valueCb = params.Parameters.Property.ValueCb;
+
+ // we're going to return 0 entities, so only the base structure
+ // is needed.
+ minSize = sizeof(VAD_ENTITIES);
+
+ if (valueCb == 0)
+ {
+ outDataCb = minSize;
+ status = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (valueCb < minSize)
+ {
+ outDataCb = 0;
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ //
+ // Reset buffer.
+ //
+ RtlZeroMemory(value, valueCb);
+
+ // we do not have disco info for this sample driver, so
+ // we have no entities to copy, but an empty list is sufficient
+ // for testing.
+
+ outDataCb = minSize;
+ status = STATUS_SUCCESS;
+ }
+
+ WdfRequestCompleteWithInformation(Request, status, outDataCb);
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitDeviceKwsCapability(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ ACX_REQUEST_PARAMETERS params;
+ ULONG_PTR outDataCb = 0;
+ PDEVICE_KWS_CAPABILITY_DESCRIPTOR value;
+ ULONG valueCb;
+ ULONG_PTR minSize;
+ PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx;
+
+ PAGED_CODE();
+
+ circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object);
+
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+ AcxRequestGetParameters(Request, &params);
+
+ ASSERT(params.Type == AcxRequestTypeProperty);
+ ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbGet);
+
+ value = (PDEVICE_KWS_CAPABILITY_DESCRIPTOR)params.Parameters.Property.Value;
+ valueCb = params.Parameters.Property.ValueCb;
+
+ //
+ // Compute min size.
+ //
+
+ minSize = sizeof(DEVICE_KWS_CAPABILITY_DESCRIPTOR);
+
+ if (valueCb == 0)
+ {
+ outDataCb = minSize;
+ status = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (valueCb < minSize)
+ {
+ outDataCb = 0;
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ //
+ // Reset buffer.
+ //
+ RtlZeroMemory(value, valueCb);
+
+ // Get the Device KWS Capabilities
+ // In this sample, just return that Buffered is supported
+ value->DataPathsSupported = SupportedDataPathsBufferedRaw;
+
+ //
+ // All done.
+ //
+ outDataCb = minSize;
+ status = STATUS_SUCCESS;
+ }
+
+ WdfRequestCompleteWithInformation(Request, status, outDataCb);
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitSetKwsAccessEvents(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ ACX_REQUEST_PARAMETERS params;
+ ULONG_PTR outDataCb = 0; // default no size info
+ PSDCA_KWS_NOTIFICATIONS value;
+ ULONG valueCb;
+ ULONG minSize;
+ PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx;
+
+ PAGED_CODE();
+
+ circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object);
+
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+ AcxRequestGetParameters(Request, &params);
+
+ ASSERT(params.Type == AcxRequestTypeProperty);
+ ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbSet);
+
+ minSize = sizeof(SDCA_KWS_NOTIFICATIONS);
+
+ value = (PSDCA_KWS_NOTIFICATIONS)params.Parameters.Property.Value;
+ valueCb = params.Parameters.Property.ValueCb;
+
+ if (valueCb == 0)
+ {
+ outDataCb = minSize;
+ status = STATUS_BUFFER_OVERFLOW;
+ goto exit;
+ }
+
+ if (valueCb < minSize)
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto exit;
+ }
+
+ circuitCtx->KwsSuspendEvent = value->Suspend;
+ circuitCtx->KwsResumeEvent = value->Resume;
+
+ status = STATUS_SUCCESS;
+
+exit:
+
+ WdfRequestCompleteWithInformation(Request, status, outDataCb);
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitConfigureVadPort(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ ACX_REQUEST_PARAMETERS params;
+ ULONG_PTR outDataCb = 0; // default no size info
+ PSDCA_KWS_PREPARE_PARAMS value;
+ ULONG valueCb;
+ ULONG minSize;
+ PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx;
+
+ PAGED_CODE();
+
+ circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object);
+
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+ AcxRequestGetParameters(Request, &params);
+
+ ASSERT(params.Type == AcxRequestTypeProperty);
+ ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbSet);
+
+ if (circuitCtx->KwsActiveVadStream)
+ {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ goto exit;
+ }
+
+ minSize = sizeof(SDCA_KWS_PREPARE_PARAMS);
+
+ value = (PSDCA_KWS_PREPARE_PARAMS)params.Parameters.Property.Value;
+ valueCb = params.Parameters.Property.ValueCb;
+
+ if (valueCb == 0)
+ {
+ outDataCb = minSize;
+ status = STATUS_BUFFER_OVERFLOW;
+ goto exit;
+ }
+
+ if (valueCb < minSize)
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ goto exit;
+ }
+
+ if (value->DetectionFormat.Format.cbSize > sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))
+ {
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ // Set up the hardware for KWS
+ circuitCtx->KwsActiveVadStream = TRUE;
+ status = STATUS_SUCCESS;
+
+exit:
+
+ WdfRequestCompleteWithInformation(Request, status, outDataCb);
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitCleanupVadPort(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ NTSTATUS status = STATUS_NOT_SUPPORTED;
+ ACX_REQUEST_PARAMETERS params;
+ ULONG_PTR outDataCb = 0; // default no size info
+ PCODEC_CAPTURE_CIRCUIT_CONTEXT circuitCtx;
+
+ PAGED_CODE();
+
+ circuitCtx = GetCaptureCircuitContext((ACXCIRCUIT)Object);
+
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+ AcxRequestGetParameters(Request, &params);
+
+ ASSERT(params.Type == AcxRequestTypeProperty);
+ ASSERT(params.Parameters.Property.Verb == AcxPropertyVerbSet);
+
+ if (!circuitCtx->KwsActiveVadStream)
+ {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ goto exit;
+ }
+
+ // Deconfigure hardware
+ circuitCtx->KwsActiveVadStream = FALSE;
+ status = STATUS_SUCCESS;
+
+exit:
+
+ WdfRequestCompleteWithInformation(Request, status, outDataCb);
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_EvtAcxPinSetDataFormat(
+ _In_ ACXPIN Pin,
+ _In_ ACXDATAFORMAT DataFormat
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Pin);
+ UNREFERENCED_PARAMETER(DataFormat);
+
+
+ return STATUS_NOT_SUPPORTED;
+}
+
+#pragma code_seg()
+VOID
+CodecC_EvtPinContextCleanup(
+ _In_ WDFOBJECT WdfPin
+)
+/*++
+
+Routine Description:
+
+ In this callback, it cleans up pin context.
+
+Arguments:
+
+ WdfDevice - WDF device object
+
+Return Value:
+
+ NULL
+
+--*/
+{
+ UNREFERENCED_PARAMETER(WdfPin);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecC_EvtCircuitRequestPreprocess(
+ _In_ ACXOBJECT Object,
+ _In_ ACXCONTEXT DriverContext,
+ _In_ WDFREQUEST Request
+)
+/*++
+
+Routine Description:
+
+ This function is an example of a preprocess routine.
+
+--*/
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(DriverContext);
+
+ ASSERT(Object != NULL);
+ ASSERT(DriverContext);
+ ASSERT(Request);
+
+
+ //
+ // Just give the request back to ACX.
+ //
+ (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecC_EvtStreamRequestPreprocess(
+ _In_ ACXOBJECT Object,
+ _In_ ACXCONTEXT DriverContext,
+ _In_ WDFREQUEST Request
+)
+/*++
+
+Routine Description:
+
+ This function is an example of a preprocess routine.
+
+--*/
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(DriverContext);
+
+ ASSERT(Object != NULL);
+ ASSERT(DriverContext);
+ ASSERT(Request);
+
+
+ //
+ // Just give the request back to ACX.
+ //
+ (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request);
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_AddCaptures(
+ _In_ WDFDRIVER Driver,
+ _In_ WDFDEVICE Device
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ PAGED_CODE();
+
+ //
+ // Add a static capture device.
+ //
+ RETURN_NTSTATUS_IF_FAILED(CodecC_AddStaticCapture(Device));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_AddStaticCapture(
+ _In_ WDFDEVICE Device
+)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ //
+ // Alloc audio context to current device.
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_CAPTURE_DEVICE_CONTEXT);
+ PCODEC_CAPTURE_DEVICE_CONTEXT captureDevCtx;
+ RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&captureDevCtx));
+
+ ASSERT(captureDevCtx);
+
+ //
+ // Create a capture circuit associated with this device.
+ //
+ ACXCIRCUIT captureCircuit = NULL;
+ RETURN_NTSTATUS_IF_FAILED(CodecC_CreateCaptureCircuit(Device, &captureCircuit));
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_SdcaXuSetCaptureEndpointConfig(Device, captureCircuit));
+
+ devCtx->Capture = captureCircuit;
+
+ return status;
+}
+
+EXTERN_C const GUID DECLSPEC_SELECTANY CODEC_CIRCUIT_CAPTURE_GUID;
+EXTERN_C const GUID DECLSPEC_SELECTANY EXTENSION_CIRCUIT_CAPTURE_GUID;
+EXTERN_C const GUID DECLSPEC_SELECTANY SYSTEM_CONTAINER_GUID;
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetCaptureEndpointConfig(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit
+)
+{
+ PAGED_CODE();
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ DECLARE_CONST_UNICODE_STRING(circuitName, L"ExtensionMicrophone0");
+ DECLARE_CONST_UNICODE_STRING(circuitUri, EXT_CAPTURE_CIRCUIT_URI);
+
+#pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "memory is freed by scope_exit")
+ PSDCAXU_ACX_CIRCUIT_CONFIG exCircuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
+ sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength,
+ DRIVER_TAG);
+ RETURN_NTSTATUS_IF_TRUE(NULL == exCircuitConfig, STATUS_INSUFFICIENT_RESOURCES);
+ auto exConfigFree = scope_exit([&exCircuitConfig]() {
+ ExFreePoolWithTag(exCircuitConfig, DRIVER_TAG);
+ });
+
+ //
+ // Provide circuit configuration to SDCA XU driver
+ // SDCA XU driver will generate circuits to match this configuration
+ //
+ if (devCtx->SdcaXuData.bSdcaXu)
+ {
+ exCircuitConfig->cbSize = sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength;
+
+ exCircuitConfig->CircuitName = circuitName;
+ exCircuitConfig->CircuitName.Buffer = (PWCH)(exCircuitConfig + 1);
+ RtlCopyMemory(exCircuitConfig->CircuitName.Buffer, circuitName.Buffer, circuitName.MaximumLength);
+
+ exCircuitConfig->CircuitContext = Circuit;
+ exCircuitConfig->CircuitType = AcxCircuitTypeCapture;
+ exCircuitConfig->ContainerID = SYSTEM_CONTAINER_GUID;
+ exCircuitConfig->ComponentID = EXTENSION_CIRCUIT_CAPTURE_GUID;
+ exCircuitConfig->ComponentUri = circuitUri;
+
+ PSDCAXU_INTERFACE_V0101 exInterface = &devCtx->SdcaXuData.ExtensionInterface;
+ PVOID exContext = devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Context;
+
+ RETURN_NTSTATUS_IF_FAILED(exInterface->EvtSetEndpointConfig(exContext, SdcaXuEndpointConfigTypeAcxCircuitConfig, exCircuitConfig, exCircuitConfig->cbSize));
+ }
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_CreateCaptureCircuit(
+ _In_ WDFDEVICE Device,
+ _Out_ ACXCIRCUIT * Circuit
+)
+/*++
+
+Routine Description:
+
+ This routine builds the CODEC capture circuit.
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ //
+ // Init output value.
+ //
+ *Circuit = NULL;
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Create a circuit.
+ //
+
+ //
+ // Get a CircuitInit structure.
+ //
+ PACXCIRCUIT_INIT circuitInit = NULL;
+ circuitInit = AcxCircuitInitAllocate(Device);
+ RETURN_NTSTATUS_IF_TRUE(NULL == circuitInit, STATUS_NO_MEMORY);
+ auto circuitInitScope = scope_exit([&circuitInit]() {
+ AcxCircuitInitFree(circuitInit);
+ });
+
+ //
+ // Add circuit identifiers.
+ //
+ AcxCircuitInitSetComponentId(circuitInit, &CODEC_CIRCUIT_CAPTURE_GUID);
+
+ DECLARE_CONST_UNICODE_STRING(circuitUri, CAPTURE_CIRCUIT_URI);
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignComponentUri(circuitInit, &circuitUri));
+
+ DECLARE_CONST_UNICODE_STRING(circuitName, L"Microphone0");
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignName(circuitInit, &circuitName));
+
+ //
+ // Add circuit type.
+ //
+ AcxCircuitInitSetCircuitType(circuitInit, AcxCircuitTypeCapture);
+
+ //
+ // Assign the circuit's pnp-power callbacks.
+ //
+ ACX_CIRCUIT_PNPPOWER_CALLBACKS powerCallbacks;
+ ACX_CIRCUIT_PNPPOWER_CALLBACKS_INIT(&powerCallbacks);
+ powerCallbacks.EvtAcxCircuitPowerUp = CodecC_EvtCircuitPowerUp;
+ powerCallbacks.EvtAcxCircuitPowerDown = CodecC_EvtCircuitPowerDown;
+ AcxCircuitInitSetAcxCircuitPnpPowerCallbacks(circuitInit, &powerCallbacks);
+
+ //
+ // Set circuit-callbacks.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxRequestPreprocessCallback(
+ circuitInit,
+ CodecC_EvtCircuitRequestPreprocess,
+ (ACXCONTEXT)AcxRequestTypeAny, // dbg only
+ AcxRequestTypeAny,
+ NULL,
+ AcxItemIdNone));
+
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignAcxCreateStreamCallback(
+ circuitInit,
+ CodecC_EvtCircuitCreateStream));
+
+ //
+ // Add properties, events and methods.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(circuitInit,
+ KwsProperties,
+ ARRAYSIZE(KwsProperties)));
+
+ //
+ // Create the circuit.
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_CAPTURE_CIRCUIT_CONTEXT);
+ ACXCIRCUIT circuit;
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitCreate(Device, &attributes, &circuitInit, &circuit));
+ circuitInitScope.release();
+
+ ASSERT(circuit != NULL);
+ CODEC_CAPTURE_CIRCUIT_CONTEXT *circuitCtx;
+ circuitCtx = GetCaptureCircuitContext(circuit);
+ ASSERT(circuitCtx);
+
+ //
+ // Post circuit creation initialization.
+ //
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Add two custom circuit elements. Note that driver doesn't need to
+ // perform this step if it doesn't want to expose any circuit elements.
+ //
+
+ //
+ // Create 1st custom circuit-element.
+ //
+ ACX_ELEMENT_CONFIG elementCfg;
+ ACX_ELEMENT_CONFIG_INIT(&elementCfg);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ const int numElements = 2;
+ ACXELEMENT elements[numElements] = {0};
+ RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[0]));
+
+ ASSERT(elements[0] != NULL);
+ CODEC_ELEMENT_CONTEXT *elementCtx;
+ elementCtx = GetCodecElementContext(elements[0]);
+ ASSERT(elementCtx);
+ UNREFERENCED_PARAMETER(elementCtx);
+
+ //
+ // Create 2nd custom circuit-element.
+ //
+ ACX_ELEMENT_CONFIG_INIT(&elementCfg);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(circuit, &attributes, &elementCfg, &elements[1]));
+
+ ASSERT(elements[1] != NULL);
+ elementCtx = GetCodecElementContext(elements[1]);
+ ASSERT(elementCtx);
+ UNREFERENCED_PARAMETER(elementCtx);
+
+ //
+ // Add the circuit elements
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements)));
+
+ ///////////////////////////////////////////////////////////
+ // Create Capture Pin, using default pin id.
+ // Acx Circuit will create other pin by default.
+ //
+ // Allocate the formats this circuit supports. Use formats without
+ // channel mask for capture.
+ //
+ // PCM:44100 channel:2 24in32
+ ACX_DATAFORMAT_CONFIG formatCfg;
+ ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm44100c2_24in32_nomask);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ ACXDATAFORMAT formatPcm44100c2_24in32nomask;
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm44100c2_24in32nomask));
+
+ CODEC_FORMAT_CONTEXT *formatCtx;
+ formatCtx = GetCodecFormatContext(formatPcm44100c2_24in32nomask);
+ ASSERT(formatCtx);
+ UNREFERENCED_PARAMETER(formatCtx);
+
+ // PCM:48000 channel:2 24in32
+ ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm48000c2_24in32_nomask);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ ACXDATAFORMAT formatPcm48000c2_24in32nomask;
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm48000c2_24in32nomask));
+
+ formatCtx = GetCodecFormatContext(formatPcm48000c2_24in32nomask);
+ ASSERT(formatCtx);
+ UNREFERENCED_PARAMETER(formatCtx);
+
+ // This is the format we'll report support for with KWS. Note that DSP uses 4ch; that includes
+ // 2ch from the hardware + 2ch reference
+ ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm16000c2nomask);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ ACXDATAFORMAT formatPcm16000c2nomask;
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm16000c2nomask));
+
+ formatCtx = GetCodecFormatContext(formatPcm16000c2nomask);
+ ASSERT(formatCtx);
+ UNREFERENCED_PARAMETER(formatCtx);
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Create Capture Pin. AcxCircuit creates the other pin by default.
+ //
+
+ ACX_PIN_CALLBACKS pinCallbacks;
+ ACX_PIN_CALLBACKS_INIT(&pinCallbacks);
+ pinCallbacks.EvtAcxPinSetDataFormat = CodecC_EvtAcxPinSetDataFormat;
+
+ ACX_PIN_CONFIG pinCfg;
+ ACX_PIN_CONFIG_INIT(&pinCfg);
+ pinCfg.Type = AcxPinTypeSource;
+ pinCfg.Communication = AcxPinCommunicationNone;
+ pinCfg.Category = &KSCATEGORY_AUDIO;
+ pinCfg.PinCallbacks = &pinCallbacks;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT);
+ attributes.EvtCleanupCallback = CodecC_EvtPinContextCleanup;
+ attributes.ParentObject = circuit;
+
+ ACXPIN pin;
+ RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin));
+
+ ASSERT(pin != NULL);
+ CODEC_PIN_CONTEXT *pinCtx;
+ pinCtx = GetCodecPinContext(pin);
+ ASSERT(pinCtx);
+ UNREFERENCED_PARAMETER(pinCtx);
+
+ //
+ // Add our supported formats to the Default mode for the circuit
+ //
+ ACXDATAFORMATLIST formatList;
+ formatList = AcxPinGetRawDataFormatList(pin);
+ RETURN_NTSTATUS_IF_TRUE(NULL == formatList, STATUS_INSUFFICIENT_RESOURCES);
+
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32nomask));
+
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm48000c2_24in32nomask));
+
+ circuitCtx->KwsDataFormat = formatPcm16000c2nomask;
+
+ // Add Capture Pin, using default pin id.
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1));
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Create Bridge Pin.
+ //
+ ACX_PIN_CONFIG_INIT(&pinCfg);
+ pinCfg.Type = AcxPinTypeSink;
+ pinCfg.Communication = AcxPinCommunicationNone;
+ pinCfg.Category = &KSNODETYPE_MICROPHONE;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT);
+ attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup;
+ attributes.ParentObject = circuit;
+ RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin));
+
+ ASSERT(pin != NULL);
+
+ RETURN_NTSTATUS_IF_FAILED(AddJack(attributes, pin, SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, RGB(0, 0, 0), AcxConnTypeAtapiInternal, AcxGeoLocFront, AcxGenLocPrimaryBox, AcxPortConnIntegratedDevice));
+
+ // Add capture bridge pin
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1));
+
+
+
+ //
+ // Explicitly connect the circuit/elements. Note that driver doens't
+ // need to perform this step when circuit/elements are connected in the
+ // same order as they were added to the circuit. By default ACX connects
+ // the elements starting from the sink circuit pin and ending on the
+ // source circuit pin on both render and capture devices.
+ //
+ // circuit.pin[default_sink] -> 1st element.pin[default_in]
+ // 1st element.pin[default_out] -> 2nd element.pin[default_in]
+ // 2nd element.pin[default_out] -> circuit.pin[default_source]
+ //
+ const int numConnections = numElements + 1;
+ ACX_CONNECTION connections[numConnections];
+ ACX_CONNECTION_INIT(&connections[0], circuit, elements[0]);
+ ACX_CONNECTION_INIT(&connections[1], elements[0], elements[1]);
+ ACX_CONNECTION_INIT(&connections[2], elements[1], circuit);
+
+ //
+ // Add the connections linking circuit to elements.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddConnections(circuit, connections, SIZEOF_ARRAY(connections)));
+
+ //
+ // Set output value.
+ //
+ *Circuit = circuit;
+
+ return status;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_EvtCircuitPowerUp(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ WDF_POWER_DEVICE_STATE PreviousState
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(Circuit);
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_EvtCircuitPowerDown(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ WDF_POWER_DEVICE_STATE TargetState
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(Circuit);
+ UNREFERENCED_PARAMETER(TargetState);
+
+ return STATUS_SUCCESS;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_EvtCircuitCreateStream(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ ACXPIN Pin,
+ _In_ PACXSTREAM_INIT StreamInit,
+ _In_ ACXDATAFORMAT StreamFormat,
+ _In_ const GUID * SignalProcessingMode,
+ _In_ ACXOBJECTBAG VarArguments
+)
+/*++
+
+Routine Description:
+
+ This routine create a stream for the specified circuit.
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Pin);
+ UNREFERENCED_PARAMETER(SignalProcessingMode);
+ UNREFERENCED_PARAMETER(VarArguments);
+
+ ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW));
+
+ PCODEC_CAPTURE_DEVICE_CONTEXT devCtx;
+ devCtx = GetCaptureDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4);
+ if (VarArguments)
+ {
+ // Get the variable arguments parameter and retrive the values set by the DSP object.
+ ULONG ui4Value = 0;
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveUI4(VarArguments, &TestUI4, &ui4Value));
+
+ RETURN_NTSTATUS_IF_TRUE(ui4Value == 0, STATUS_UNSUCCESSFUL);
+
+ ui4Value++;
+
+ // Add the modified value back to object bag.
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(VarArguments, &TestUI4, ui4Value));
+ }
+
+ //
+ // Set circuit-callbacks.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback(
+ StreamInit,
+ CodecC_EvtStreamRequestPreprocess,
+ (ACXCONTEXT)AcxRequestTypeAny, // dbg only
+ AcxRequestTypeAny,
+ NULL,
+ AcxItemIdNone));
+
+ /*
+ //
+ // Add properties, events and methods.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit,
+ StreamProperties,
+ StreamPropertiesCount));
+ */
+
+ //
+ // Init streaming callbacks.
+ //
+ ACX_STREAM_CALLBACKS streamCallbacks;
+ ACX_STREAM_CALLBACKS_INIT(&streamCallbacks);
+ streamCallbacks.EvtAcxStreamPrepareHardware = Codec_EvtStreamPrepareHardware;
+ streamCallbacks.EvtAcxStreamReleaseHardware = Codec_EvtStreamReleaseHardware;
+ streamCallbacks.EvtAcxStreamRun = Codec_EvtStreamRun;
+ streamCallbacks.EvtAcxStreamPause = Codec_EvtStreamPause;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks));
+
+ //
+ // Create the stream.
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_STREAM_CONTEXT);
+ attributes.EvtDestroyCallback = Codec_EvtStreamDestroy;
+ ACXSTREAM stream;
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream));
+
+ CCaptureStreamEngine *streamEngine = NULL;
+ streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CCaptureStreamEngine(stream, StreamFormat);
+ RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_INSUFFICIENT_RESOURCES);
+
+ CODEC_STREAM_CONTEXT *streamCtx;
+ streamCtx = GetCodecStreamContext(stream);
+ ASSERT(streamCtx);
+ streamCtx->StreamEngine = (PVOID)streamEngine;
+ streamEngine = NULL;
+
+ //
+ // Post stream creation initialization.
+ //
+
+ //
+ // Create 1st custom stream-elements.
+ //
+ ACX_ELEMENT_CONFIG elementCfg;
+ ACX_ELEMENT_CONFIG_INIT(&elementCfg);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT);
+ attributes.ParentObject = stream;
+
+ ACXELEMENT elements[2] = {0};
+ RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0]));
+
+ ASSERT(elements[0] != NULL);
+ CODEC_ELEMENT_CONTEXT *elementCtx;
+ elementCtx = GetCodecElementContext(elements[0]);
+ ASSERT(elementCtx);
+ UNREFERENCED_PARAMETER(elementCtx);
+
+ //
+ // Create 2nd custom stream-elements.
+ //
+ ACX_ELEMENT_CONFIG_INIT(&elementCfg);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT);
+ attributes.ParentObject = stream;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1]));
+
+ ASSERT(elements[1] != NULL);
+ elementCtx = GetCodecElementContext(elements[1]);
+ ASSERT(elementCtx);
+ UNREFERENCED_PARAMETER(elementCtx);
+
+ //
+ // Add stream elements
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements)));
+
+ return status;
+}
+
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp
new file mode 100644
index 00000000..e4805669
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/device.cpp
@@ -0,0 +1,808 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Device.cpp
+
+Abstract:
+
+ Plug and Play module. This file contains routines to handle pnp requests.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "private.h"
+#include <devguid.h>
+#include "stdunk.h"
+#include <ks.h>
+#include <mmsystem.h>
+#include <ksmedia.h>
+#include "streamengine.h"
+#include "CircuitHelper.h"
+
+#ifndef __INTELLISENSE__
+#include "device.tmh"
+#endif
+
+UNICODE_STRING g_RegistryPath = {0}; // This is used to store the registry settings path for the driver
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS CopyRegistrySettingsPath
+(
+ _In_ PUNICODE_STRING RegistryPath
+)
+/*++
+
+Routine Description:
+
+Copies the following registry path to a global variable.
+
+\REGISTRY\MACHINE\SYSTEM\ControlSetxxx\Services\<driver>\Parameters
+
+Arguments:
+
+RegistryPath - Registry path passed to DriverEntry
+
+Returns:
+
+NTSTATUS - SUCCESS if able to configure the framework
+
+--*/
+
+{
+ PAGED_CODE();
+
+ // Initializing the unicode string, so that if it is not allocated it will not be deallocated too.
+ RtlInitUnicodeString(&g_RegistryPath, NULL);
+
+ g_RegistryPath.MaximumLength = RegistryPath->Length + sizeof(WCHAR);
+
+ g_RegistryPath.Buffer = (PWCH)ExAllocatePool2(POOL_FLAG_PAGED, g_RegistryPath.MaximumLength, DRIVER_TAG);
+
+ if (g_RegistryPath.Buffer == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // ExAllocatePool2 zeros memory.
+
+ RtlAppendUnicodeToString(&g_RegistryPath, RegistryPath->Buffer);
+
+ return STATUS_SUCCESS;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtBusDeviceAdd(
+ _In_ WDFDRIVER Driver,
+ _Inout_ PWDFDEVICE_INIT DeviceInit
+ )
+/*++
+Routine Description:
+
+ EvtDeviceAdd is called by the framework in response to AddDevice
+ call from the PnP manager. We create and initialize a device object to
+ represent a new instance of the device. All the software resources
+ should be allocated in this callback.
+
+Arguments:
+
+ Driver - Handle to a framework driver object created in DriverEntry
+
+ DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
+
+Return Value:
+
+ NTSTATUS
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // Allow ACX to add any pre-requirement it needs on this device.
+ //
+ ACX_DEVICEINIT_CONFIG devInitCfg;
+ ACX_DEVICEINIT_CONFIG_INIT(&devInitCfg);
+ RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitInitialize(DeviceInit, &devInitCfg));
+
+ //
+ // Initialize the pnpPowerCallbacks structure. Callback events for PNP
+ // and Power are specified here. If you don't supply any callbacks,
+ // the Framework will take appropriate default actions based on whether
+ // DeviceInit is initialized to be an FDO, a PDO or a filter device
+ // object.
+ //
+ WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
+ WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
+ pnpPowerCallbacks.EvtDevicePrepareHardware = Codec_EvtDevicePrepareHardware;
+ pnpPowerCallbacks.EvtDeviceReleaseHardware = Codec_EvtDeviceReleaseHardware;
+ WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
+
+ //
+ // Specify the type of context needed.
+ // Use default locking, i.e., none.
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_DEVICE_CONTEXT);
+ attributes.EvtCleanupCallback = Codec_EvtDeviceContextCleanup;
+
+ //
+ // Create the device.
+ //
+ WDFDEVICE device = NULL;
+ RETURN_NTSTATUS_IF_FAILED(WdfDeviceCreate(&DeviceInit, &attributes, &device));
+
+ //
+ // Init Codec's device context.
+ //
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(device);
+ ASSERT(devCtx != NULL);
+ devCtx->Render = NULL;
+ devCtx->Capture = NULL;
+
+ //
+ // Assume XU lower filter driver is not present
+ //
+ devCtx->SdcaXuData.bSdcaXu = FALSE;
+
+ //
+ // Allow ACX to add any post-requirement it needs on this device.
+ //
+ ACX_DEVICE_CONFIG devCfg;
+ ACX_DEVICE_CONFIG_INIT(&devCfg);
+ RETURN_NTSTATUS_IF_FAILED(AcxDeviceInitialize(device, &devCfg));
+
+ //
+ // Tell the framework to set the SurpriseRemovalOK in the DeviceCaps so
+ // that you don't get the popup in usermode (on Win2K) when you surprise
+ // remove the device.
+ //
+ WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
+ WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
+ pnpCaps.SurpriseRemovalOK = WdfTrue;
+ WdfDeviceSetPnpCapabilities(device, &pnpCaps);
+
+ //
+ // Get SDCA XU filter interface
+ //
+ RETURN_NTSTATUS_IF_FAILED_UNLESS_ALLOWED(Codec_GetSdcaXu(device), STATUS_NOT_SUPPORTED);
+
+ if (devCtx->SdcaXuData.bSdcaXu)
+ {
+ RETURN_NTSTATUS_IF_FAILED(Codec_SetSdcaXuHwConfig(device));
+ }
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_AddRenderComposites(device));
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_AddCaptureComposites(device));
+
+ //
+ // Add a render device and a capture device.
+ //
+ RETURN_NTSTATUS_IF_FAILED(CodecR_AddRenders(Driver, device));
+
+ //
+ // Add a render device and a capture device.
+ //
+ RETURN_NTSTATUS_IF_FAILED(CodecC_AddCaptures(Driver, device));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtDevicePrepareHardware(
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourceList,
+ _In_ WDFCMRESLIST ResourceListTranslated
+)
+/*++
+
+Routine Description:
+
+ In this callback, the driver does whatever is necessary to make the
+ hardware ready to use.
+
+Arguments:
+
+ Device - handle to a device
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER(ResourceList);
+ UNREFERENCED_PARAMETER(ResourceListTranslated);
+
+ PAGED_CODE();
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_SetPowerPolicy(Device));
+
+ //
+ // Add static circuit to device's list.
+ //
+ ASSERT(devCtx->Render);
+ RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Render));
+
+ ASSERT(devCtx->Capture);
+ RETURN_NTSTATUS_IF_FAILED(AcxDeviceAddCircuit(Device, devCtx->Capture));
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtDeviceReleaseHardware(
+ _In_ WDFDEVICE Device,
+ _In_ WDFCMRESLIST ResourceListTranslated
+)
+/*++
+
+Routine Description:
+
+ In this callback, the driver releases the h/w resources allocated in the
+ prepare h/w callback.
+
+Arguments:
+
+ Device - handle to a device
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(ResourceListTranslated);
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_SetPowerPolicy(
+ _In_ WDFDEVICE Device
+)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings;
+ //WDF_DEVICE_POWER_POLICY_WAKE_SETTINGS wakeSettings;
+
+ //
+ // Init the idle policy structure.
+ //
+ //WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCanWakeFromS0);
+ WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0);
+ idleSettings.IdleTimeout = 10000; // 10-sec
+
+ RETURN_NTSTATUS_IF_FAILED(WdfDeviceAssignS0IdleSettings(Device, &idleSettings));
+
+ return status;
+}
+
+#pragma code_seg()
+
+DEFINE_GUID(CODEC_CIRCUIT_RENDER_GUID,
+0xfd4b6e78, 0x51e0, 0x4aa6, 0x90, 0x98, 0xbb, 0xcb, 0x70, 0x89, 0xcb, 0x6a);
+
+DEFINE_GUID(EXTENSION_CIRCUIT_RENDER_GUID,
+0x656ab905, 0x55fb, 0x4b08, 0xb6, 0x01, 0xd7, 0xf0, 0xc1, 0xce, 0x36, 0x2c);
+
+// {17F5B19F-C2C7-4B53-AFB9-49A0283D0DCE}
+DEFINE_GUID(DSP_CIRCUIT_SPEAKER_GUID,
+ 0x17f5b19f, 0xc2c7, 0x4b53, 0xaf, 0xb9, 0x49, 0xa0, 0x28, 0x3d, 0xd, 0xce);
+
+DEFINE_GUID(CODEC_CIRCUIT_CAPTURE_GUID,
+0x67ec5936, 0xa395, 0x4e93, 0xbe, 0x8a, 0xfc, 0xed, 0xe3, 0x1b, 0xad, 0x40);
+
+DEFINE_GUID(EXTENSION_CIRCUIT_CAPTURE_GUID,
+0x44c69385, 0xa012, 0x405f, 0x8a, 0x9a, 0x7b, 0x44, 0x29, 0x71, 0xc8, 0x50);
+
+// {6F9EACF7-CD2D-4030-9E49-7CC4ADEFF192}
+DEFINE_GUID(DSP_CIRCUIT_MICROPHONE_GUID,
+ 0x6f9eacf7, 0xcd2d, 0x4030, 0x9e, 0x49, 0x7c, 0xc4, 0xad, 0xef, 0xf1, 0x92);
+
+DEFINE_GUID(SYSTEM_CONTAINER_GUID,
+0x00000000, 0x0000, 0x0000, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
+
+
+#define DSP_FACTORY_URI L"acpi:obj-path:\\_SB.PC00.HDAS"
+
+#define RENDER_CIRCUIT_UNIQUE_ID L"{613fd364-64bb-4b69-99bc-5b075ea9756b}"
+#define RENDER_CIRCUIT_FRIENDLY_NAME L"Speaker-360"
+#define RENDER_CIRCUIT_NAME L"Speaker"
+#define CAPTURE_CIRCUIT_UNIQUE_ID L"{3A509246-5902-4AA2-9E06-C7C8D10461C3}"
+#define CAPTURE_CIRCUIT_FRIENDLY_NAME L"Microphone-360"
+#define CAPTURE_CIRCUIT_NAME L"Microphone"
+
+#define CIRCUIT_RENDER_VENDOR_BLOB "Streaming_Speaker"
+#define CIRCUIT_CAPTURE_VENDOR_BLOB "Streaming_MicrophoneArray"
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+Codec_AddRenderComposites(_In_ WDFDEVICE Device)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Device);
+
+ PAGED_CODE();
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_AddComposites(Device, CompositeType_RENDER));
+
+ return status;
+}
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+Codec_AddCaptureComposites(_In_ WDFDEVICE Device)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Device);
+
+ PAGED_CODE();
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_AddComposites(Device, CompositeType_CAPTURE));
+
+ return status;
+}
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+Codec_AddComposites(_In_ WDFDEVICE Device, _In_ CompositeType compositeType)
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ UNICODE_STRING circuit_IDs[] = {
+ { sizeof(RENDER_CIRCUIT_UNIQUE_ID) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_UNIQUE_ID), RENDER_CIRCUIT_UNIQUE_ID },
+ { sizeof(CAPTURE_CIRCUIT_UNIQUE_ID) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_UNIQUE_ID), CAPTURE_CIRCUIT_UNIQUE_ID}
+ };
+
+ UNICODE_STRING circuit_friendly_names[] = {
+ { sizeof(RENDER_CIRCUIT_FRIENDLY_NAME) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_FRIENDLY_NAME), RENDER_CIRCUIT_FRIENDLY_NAME },
+ { sizeof(CAPTURE_CIRCUIT_FRIENDLY_NAME) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_FRIENDLY_NAME), CAPTURE_CIRCUIT_FRIENDLY_NAME}
+ };
+
+ UNICODE_STRING circuit_names[] = {
+ { sizeof(RENDER_CIRCUIT_NAME) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_NAME), RENDER_CIRCUIT_NAME },
+ { sizeof(CAPTURE_CIRCUIT_NAME) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_NAME), CAPTURE_CIRCUIT_NAME}
+ };
+
+ UNICODE_STRING codec_circuit_uris[] = {
+ { sizeof(RENDER_CIRCUIT_URI) - sizeof(WCHAR), sizeof(RENDER_CIRCUIT_URI), RENDER_CIRCUIT_URI },
+ { sizeof(CAPTURE_CIRCUIT_URI) - sizeof(WCHAR), sizeof(CAPTURE_CIRCUIT_URI), CAPTURE_CIRCUIT_URI}
+ };
+
+ UNICODE_STRING extension_circuit_uris[] = {
+ { sizeof(EXT_RENDER_CIRCUIT_URI) - sizeof(WCHAR), sizeof(EXT_RENDER_CIRCUIT_URI), EXT_RENDER_CIRCUIT_URI },
+ { sizeof(EXT_CAPTURE_CIRCUIT_URI) - sizeof(WCHAR), sizeof(EXT_CAPTURE_CIRCUIT_URI), EXT_CAPTURE_CIRCUIT_URI}
+ };
+
+ GUID dsp_circuit_guids[] = {
+ DSP_CIRCUIT_SPEAKER_GUID,
+ DSP_CIRCUIT_MICROPHONE_GUID
+ };
+
+ UNICODE_STRING dsp_factory_uris[] = {
+ { sizeof(DSP_FACTORY_URI) - sizeof(WCHAR), sizeof(DSP_FACTORY_URI), DSP_FACTORY_URI },
+ { sizeof(DSP_FACTORY_URI) - sizeof(WCHAR), sizeof(DSP_FACTORY_URI), DSP_FACTORY_URI}
+ };
+
+ const char* dsp_factory_vendor_blobs[] = {
+ CIRCUIT_RENDER_VENDOR_BLOB,
+ CIRCUIT_CAPTURE_VENDOR_BLOB
+ };
+
+ PCODEC_DEVICE_CONTEXT deviceCtx = NULL;
+ deviceCtx = GetCodecDeviceContext(Device);
+ ASSERT(deviceCtx);
+
+ //
+ // May be called again for rebalance
+ // Add composites only once
+ //
+ RETURN_NTSTATUS_IF_TRUE(0 != deviceCtx->refComposite[compositeType], STATUS_SUCCESS);
+
+ //
+ // Object bag
+ //
+ // This obj-bag config setting is shared by all composite/circuit templates.
+ ACX_OBJECTBAG_CONFIG objBagCfg;
+ ACX_OBJECTBAG_CONFIG_INIT(&objBagCfg);
+
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = AcxGetManager(NULL);
+
+ ACXOBJECTBAG objBag = NULL;
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag));
+ auto objBag_scope = scope_exit([&objBag]() {
+ if (objBag != NULL)
+ {
+ WdfObjectDelete(objBag);
+ }
+ });
+
+ //
+ // Add a test unsigned int 4 bytes to the object bag
+ //
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 0));
+
+ //
+ // Add unique circuit ID to the object bag
+ // This unique Id will be picked up by DSP circuit
+ //
+ DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(UniqueID);
+ GUID uniqueID = { 0 };
+ RETURN_NTSTATUS_IF_FAILED(RtlGUIDFromString(&circuit_IDs[compositeType], &uniqueID));
+
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddGuid(objBag, &UniqueID, uniqueID));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddUnicodeStrings(objBag, circuit_friendly_names[compositeType], circuit_names[compositeType]));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddEndpointId(objBag, 9));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddDataPortNumber(objBag, 9));
+
+ //
+ // Composite template.
+ //
+ ULONG circuitsInTemplate = 0;
+ ACXCIRCUITTEMPLATE circuits[3] = { 0 };
+ ACX_COMPOSITE_TEMPLATE_CONFIG compositeCfg;
+ ACX_COMPOSITE_TEMPLATE_CONFIG_INIT(&compositeCfg);
+ compositeCfg.Properties = objBag;
+ compositeCfg.Flags |= AcxCompositeTemplateConfigSingleton;
+
+ ACXCOMPOSITETEMPLATE composite = NULL;
+ RETURN_NTSTATUS_IF_FAILED(AcxCompositeTemplateCreate(WdfGetDriver(),
+ &attributes,
+ &compositeCfg,
+ &composite));
+
+ auto composite_scope = scope_exit([&composite]() {
+ WdfObjectDelete(composite);
+ composite = NULL;
+ });
+
+ objBag = NULL;
+
+ // This attribute setting is shared by all the circuit templates.
+ WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
+ attributes.ParentObject = composite;
+
+ // Codec template.
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 2));
+
+ ACX_CIRCUIT_TEMPLATE_CONFIG circuitCfg1;
+ ACX_CIRCUIT_TEMPLATE_CONFIG_INIT(&circuitCfg1);
+ circuitCfg1.CircuitProperties = objBag;
+ circuitCfg1.CircuitUri = &codec_circuit_uris[compositeType];
+
+ ULONG codecIndex = circuitsInTemplate;
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitTemplateCreate(WdfGetDriver(),
+ &attributes,
+ &circuitCfg1,
+ &circuits[circuitsInTemplate++]));
+
+ objBag = NULL;
+
+ // XU template.
+ //
+ // Check if XU is present
+ // and compose with Xu circuit
+ //
+ if (deviceCtx->SdcaXuData.bSdcaXu)
+ {
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 2));
+
+ ACX_CIRCUIT_TEMPLATE_CONFIG circuitCfg2;
+ ACX_CIRCUIT_TEMPLATE_CONFIG_INIT(&circuitCfg2);
+ circuitCfg2.CircuitProperties = objBag;
+ circuitCfg2.CircuitUri = &extension_circuit_uris[compositeType];
+
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitTemplateCreate(WdfGetDriver(),
+ &attributes,
+ &circuitCfg2,
+ &circuits[circuitsInTemplate++]));
+
+ objBag = NULL;
+ }
+
+ // Dsp template.
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagCreate(&attributes, &objBagCfg, &objBag));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddTestUI4(objBag, 3));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddCircuitId(objBag, dsp_circuit_guids[compositeType]));
+
+ RETURN_NTSTATUS_IF_FAILED(ObjBagAddBlob(objBag, dsp_factory_vendor_blobs[compositeType]));
+
+ ACX_CIRCUIT_TEMPLATE_CONFIG circuitCfg3;
+ ACX_CIRCUIT_TEMPLATE_CONFIG_INIT(&circuitCfg3);
+ circuitCfg3.CircuitProperties = objBag;
+ circuitCfg3.FactoryUri = &dsp_factory_uris[compositeType];
+ circuitCfg3.Flags |= AcxCircuitTemplateCircuitOnDemand;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitTemplateCreate(WdfGetDriver(),
+ &attributes,
+ &circuitCfg3,
+ &circuits[circuitsInTemplate++]));
+
+ objBag = NULL;
+ objBag_scope.release();
+
+ RETURN_NTSTATUS_IF_FAILED(AcxCompositeTemplateAssignCircuits(composite, circuits, circuitsInTemplate));
+
+ // Select the core circuit.
+ AcxCompositeTemplateSetCoreCircuit(composite, circuits[codecIndex]);
+
+ // Final step.
+ RETURN_NTSTATUS_IF_FAILED(AcxManagerAddCompositeTemplate(AcxGetManager(NULL), composite));
+
+ deviceCtx->Composite[compositeType] = composite;
+ composite_scope.release();
+
+ deviceCtx->refComposite[compositeType]++;
+
+ return status;
+}
+
+#pragma code_seg()
+NTSTATUS
+Codec_RemoveComposites(_In_ WDFDEVICE Device)
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT deviceCtx = NULL;
+ deviceCtx = GetCodecDeviceContext(Device);
+ ASSERT(deviceCtx);
+
+ for (ULONG compositeType = CompositeType_RENDER; compositeType <= CompositeType_CAPTURE; )
+ {
+ if (deviceCtx->refComposite[compositeType])
+ {
+ deviceCtx->refComposite[compositeType]--;
+ if (deviceCtx->refComposite[compositeType] == 0)
+ {
+ if (deviceCtx->Composite[compositeType] != NULL)
+ {
+ RETURN_NTSTATUS_IF_FAILED(AcxManagerRemoveCompositeTemplate(AcxGetManager(NULL), deviceCtx->Composite[compositeType]));
+
+ WdfObjectDelete(deviceCtx->Composite[compositeType]);
+ deviceCtx->Composite[compositeType] = NULL;
+ }
+ }
+ }
+
+ compositeType++;
+ }
+
+ return status;
+}
+
+#pragma code_seg()
+VOID
+Codec_EvtDeviceContextCleanup(
+ _In_ WDFOBJECT WdfDevice
+ )
+/*++
+
+Routine Description:
+
+ In this callback, it cleans up device context.
+
+Arguments:
+
+ WdfDevice - WDF device object
+
+Return Value:
+
+ NULL
+
+--*/
+{
+ WDFDEVICE device;
+ PCODEC_DEVICE_CONTEXT devCtx;
+
+
+ device = (WDFDEVICE)WdfDevice;
+ devCtx = GetCodecDeviceContext(device);
+ ASSERT(devCtx != NULL);
+
+ Codec_RemoveComposites(device);
+
+ if (devCtx->SdcaXuData.XUEntities)
+ {
+ ExFreePoolWithTag(devCtx->SdcaXuData.XUEntities, DRIVER_TAG);
+ devCtx->SdcaXuData.numXUEntities = 0;
+ }
+ if (devCtx->SdcaXuData.InterruptInfo)
+ {
+ ExFreePoolWithTag(devCtx->SdcaXuData.InterruptInfo, DRIVER_TAG);
+ devCtx->SdcaXuData.InterruptInfo = NULL;
+ }
+}
+
+#pragma code_seg()
+VOID
+Codec_EvtStreamDestroy(
+ _In_ WDFOBJECT Object
+ )
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ ctx = GetCodecStreamContext((ACXSTREAM)Object);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+ ctx->StreamEngine = NULL;
+ delete streamEngine;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtStreamGetHwLatency(
+ _In_ ACXSTREAM Stream,
+ _Out_ ULONG * FifoSize,
+ _Out_ ULONG * Delay
+)
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ PAGED_CODE();
+
+ ctx = GetCodecStreamContext(Stream);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+
+ return streamEngine->GetHWLatency(FifoSize, Delay);
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtStreamPrepareHardware(
+ _In_ ACXSTREAM Stream
+ )
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ PAGED_CODE();
+
+ ctx = GetCodecStreamContext(Stream);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+
+ return streamEngine->PrepareHardware();
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtStreamReleaseHardware(
+ _In_ ACXSTREAM Stream
+ )
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ PAGED_CODE();
+
+ ctx = GetCodecStreamContext(Stream);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+
+ return streamEngine->ReleaseHardware();
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtStreamRun(
+ _In_ ACXSTREAM Stream
+ )
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ PAGED_CODE();
+
+ ctx = GetCodecStreamContext(Stream);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+
+ return streamEngine->Run();
+}
+
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtStreamPause(
+ _In_ ACXSTREAM Stream
+ )
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ PAGED_CODE();
+
+ ctx = GetCodecStreamContext(Stream);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+
+ return streamEngine->Pause();
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_EvtStreamAssignDrmContentId(
+ _In_ ACXSTREAM Stream,
+ _In_ ULONG DrmContentId,
+ _In_ PACXDRMRIGHTS DrmRights
+ )
+{
+ PCODEC_STREAM_CONTEXT ctx;
+ CStreamEngine * streamEngine = NULL;
+
+ PAGED_CODE();
+
+ ctx = GetCodecStreamContext(Stream);
+
+ streamEngine = (CStreamEngine*)ctx->StreamEngine;
+
+ return streamEngine->AssignDrmContentId(DrmContentId, DrmRights);
+}
+
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp
new file mode 100644
index 00000000..4c9f937e
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/driver.cpp
@@ -0,0 +1,218 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Module Name:
+
+ Driver.cpp
+
+Abstract:
+
+ Sample soundwire Codec driver
+
+Environment:
+
+ Kernel mode only
+
+--*/
+
+#include "private.h"
+
+#ifndef __INTELLISENSE__
+#include "driver.tmh"
+#endif
+
+RECORDER_LOG g_SDCAVCodecLog{ nullptr };
+
+INIT_CODE_SEG
+void
+Test_ClientVersionHigherThanFramework()
+{
+ PAGED_CODE();
+
+ // example on how to check if a function is available.
+ /*
+ if (ACX_IS_FUNCTION_AVAILABLE(AcxCircuitCreate)) {
+ DbgPrint("Available: AcxCircuitCreate\n");
+ }
+ else
+ {
+ DbgPrint("Not available: AcxCircuitCreate\n");
+ ASSERT(FALSE);
+ }
+ */
+
+ if (ACX_IS_FIELD_AVAILABLE(ACX_DEVICEINIT_CONFIG, SynchronizationScope)) {
+ ACX_DEVICEINIT_CONFIG config;
+ ACX_DEVICEINIT_CONFIG_INIT(&config);
+ DbgPrint("Available: ACX_DEVICEINIT_CONFIG.SynchronizationScope\n");
+ }
+ else
+ {
+ DbgPrint("Not available: ACX_DEVICEINIT_CONFIG.SynchronizationScope\n");
+ ASSERT(FALSE);
+ }
+}
+
+PAGED_CODE_SEG
+VOID Codec_DriverUnload(_In_ WDFDRIVER Driver)
+{
+ PAGED_CODE();
+
+ if (!Driver)
+ {
+ ASSERT(FALSE);
+ return;
+ }
+
+ WPP_CLEANUP(WdfDriverWdmGetDriverObject(Driver));
+
+ if (g_RegistryPath.Buffer != NULL)
+ {
+ ExFreePool(g_RegistryPath.Buffer);
+ RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath));
+ }
+
+ return;
+}
+
+INIT_CODE_SEG
+NTSTATUS
+DriverEntry(
+ _In_ PDRIVER_OBJECT DriverObject,
+ _In_ PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Description:
+ DriverEntry initializes the driver and is the first routine called by the
+ system after the driver is loaded.
+
+Parameters Description:
+
+ DriverObject - represents the instance of the function driver that is loaded
+ into memory. DriverEntry must initialize members of DriverObject before it
+ returns to the caller. DriverObject is allocated by the system before the
+ driver is loaded, and it is released by the system after the system unloads
+ the function driver from memory.
+
+ RegistryPath - represents the driver specific path in the Registry.
+ The function driver can use the path to store driver related data between
+ reboots. The path does not store hardware instance specific data.
+
+Return Value:
+
+ STATUS_SUCCESS if successful,
+ STATUS_UNSUCCESSFUL otherwise.
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WPP_INIT_TRACING(DriverObject, RegistryPath);
+
+ auto exit = scope_exit([&status, &DriverObject]() {
+ if (!NT_SUCCESS(status))
+ {
+ if (g_RegistryPath.Buffer != NULL)
+ {
+ ExFreePool(g_RegistryPath.Buffer);
+ RtlZeroMemory(&g_RegistryPath, sizeof(g_RegistryPath));
+ }
+
+ WPP_CLEANUP(DriverObject);
+ }
+ else
+ {
+ DrvLogInfo(g_SDCAVCodecLog, FLAG_INIT, "ACX SDCA Virtual Codec Driver Init complete, %!STATUS!", status);
+ }
+ });
+
+ RETURN_NTSTATUS_IF_FAILED(CopyRegistrySettingsPath(RegistryPath));
+
+ //
+ // Initiialize driver config to control the attributes that
+ // are global to the driver. Note that framework by default
+ // provides a driver unload routine. If you create any resources
+ // in the DriverEntry and want to be cleaned in driver unload,
+ // you can override that by manually setting the EvtDriverUnload in the
+ // config structure. In general xxx_CONFIG_INIT macros are provided to
+ // initialize most commonly used members.
+ //
+
+ WDF_DRIVER_CONFIG wdfCfg;
+ WDF_DRIVER_CONFIG_INIT(&wdfCfg, Codec_EvtBusDeviceAdd);
+ wdfCfg.EvtDriverUnload = Codec_DriverUnload;
+
+ //
+ // Add a driver context. (for illustration purposes only).
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_DRIVER_CONTEXT);
+
+ //
+ // Create a framework driver object to represent our driver.
+ //
+ WDFDRIVER driver;
+ RETURN_NTSTATUS_IF_FAILED(WdfDriverCreate(
+ DriverObject,
+ RegistryPath,
+ &attributes, // Driver Attributes
+ &wdfCfg, // Driver Config Info
+ &driver // hDriver
+ ));
+
+ RECORDER_CONFIGURE_PARAMS recorderConfig;
+ RECORDER_CONFIGURE_PARAMS_INIT(&recorderConfig);
+ recorderConfig.CreateDefaultLog = FALSE;
+ WppRecorderConfigure(&recorderConfig);
+
+ RECORDER_LOG_CREATE_PARAMS recorderLogCreateParams;
+ RECORDER_LOG_CREATE_PARAMS_INIT(&recorderLogCreateParams, NULL);
+ recorderLogCreateParams.TotalBufferSize = WPP_TOTAL_BUFFER_SIZE;
+ recorderLogCreateParams.ErrorPartitionSize = WPP_ERROR_PARTITION_SIZE;
+
+ RtlStringCbPrintfA(recorderLogCreateParams.LogIdentifier,
+ RECORDER_LOG_IDENTIFIER_MAX_CHARS,
+ "SDCAVCodec");
+
+ RECORDER_LOG logHandle = NULL;
+ status = WppRecorderLogCreate(&recorderLogCreateParams, &logHandle);
+ if (!NT_SUCCESS(status))
+ {
+ logHandle = NULL;
+
+ // Non fatal failure
+ status = STATUS_SUCCESS;
+ }
+
+ g_SDCAVCodecLog = logHandle;
+
+ //
+ // Post init.
+ //
+ ACX_DRIVER_CONFIG acxCfg;
+ ACX_DRIVER_CONFIG_INIT(&acxCfg);
+
+ RETURN_NTSTATUS_IF_FAILED(AcxDriverInitialize(driver, &acxCfg));
+
+ //
+ // Test ACX bindings.
+ //
+ ACX_DRIVER_VERSION_AVAILABLE_PARAMS ver;
+ ACX_DRIVER_VERSION_AVAILABLE_PARAMS_INIT(&ver, 1, 0);
+ if (!AcxDriverIsVersionAvailable(driver, &ver)) {
+ status = STATUS_DRIVER_INTERNAL_ERROR;
+ DbgPrint("Unexpected ACX library version.\n");
+ ASSERT(FALSE);
+ }
+ RETURN_NTSTATUS_IF_FAILED(status);
+
+ Test_ClientVersionHigherThanFramework();
+
+ return status;
+}
+
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h
new file mode 100644
index 00000000..602133ba
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/private.h
@@ -0,0 +1,522 @@
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ private.h
+
+Abstract:
+
+ Contains structure definitions and function prototypes private to
+ the driver.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#ifndef _PRIVATE_H_
+#define _PRIVATE_H_
+
+#include "cpp_utils.h"
+
+#include "NewDelete.h"
+
+/* make prototypes usable from C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma warning(disable:4200) //
+#pragma warning(disable:4201) // nameless struct/union
+#pragma warning(disable:4214) // bit field types other than int
+
+#include <initguid.h>
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <ntintsafe.h>
+
+#pragma warning(default:4200)
+#pragma warning(default:4201)
+#pragma warning(default:4214)
+
+#include <wdf.h>
+#include <acx.h>
+
+#include "SoundWireController.h"
+#include "SdcaXu.h"
+
+#include "trace.h"
+
+#include <TestProperties.h>
+
+#define PAGED_CODE_SEG __declspec(code_seg("PAGE"))
+#define INIT_CODE_SEG __declspec(code_seg("INIT"))
+
+extern RECORDER_LOG g_SDCAVCodecLog;
+
+// Simple ACX driver
+#define DRIVER_TAG (ULONG) 'Ccds'
+
+// Number of millisecs per sec.
+#define MS_PER_SEC 1000
+
+// Number of hundred nanosecs per sec.
+#define HNS_PER_SEC 10000000
+
+// Compatible ID for render/capture
+#define ACX_CODEC_TEST_COMPATIBLE_ID L"{99a0ee05-7167-4b63-843d-19d6d285942e}"
+
+// Container ID for render/capture
+#define ACX_CODEC_TEST_CONTAINER_ID L"{00000000-0000-0000-ffff-ffffffffffff}"
+
+#define RENDER_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\RENDER"
+#define EXT_RENDER_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\RENDER_xu"
+#define CAPTURE_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\CAPTURE"
+#define EXT_CAPTURE_CIRCUIT_URI L"test:obj-path:\\SDCAVCODEC\\CAPTURE_xu"
+
+#undef MIN
+#undef MAX
+#define MIN(a,b) ((a) > (b) ? (b) : (a))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
+#ifndef BOOL
+typedef int BOOL;
+#endif
+
+#ifndef SIZEOF_ARRAY
+#define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0]))
+#endif // !defined(SIZEOF_ARRAY)
+
+#ifndef RGB
+#define RGB(r, g, b) (DWORD)(r << 16 | g << 8 | b)
+#endif
+
+
+//
+// Example Acpi blob for Hardware configuration
+//
+typedef struct _SdcaXuAcpiBlob
+{
+ // Number of endpoints
+ ULONG NumEndpoints;
+
+}SdcaXuAcpiBlob, *PSdcaXuAcpiBlob;
+
+#define ALL_CHANNELS_ID UINT32_MAX
+#define MAX_CHANNELS 2
+
+//
+// Ks support.
+//
+#define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \
+ KSPROPERTY_TYPE_GET | \
+ KSPROPERTY_TYPE_SET
+
+//
+// Define CODEC driver context.
+//
+typedef struct _CODEC_DRIVER_CONTEXT {
+ ULONG reserved;
+} CODEC_DRIVER_CONTEXT, *PCODEC_DRIVER_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_DRIVER_CONTEXT, GetCodecDriverContext)
+
+//
+// Extension Unit specific data
+//
+typedef struct _SDCAXU_DATA
+{
+ BOOLEAN bSdcaXu;
+ BOOLEAN bExtensionJackOVerride;
+ SDCAXU_INTERFACE_V0101 ExtensionInterface;
+ ULONG numXUEntities;
+ ULONG *XUEntities;
+ PSDCAXU_INTERRUPT_INFO InterruptInfo;
+}SDCAXU_DATA, *PSDCAXU_DATA;
+
+//
+// Define CODEC device context.
+//
+typedef struct _CODEC_DEVICE_CONTEXT {
+ ACXCIRCUIT Render;
+ ACXCIRCUIT Capture;
+ ACXCOMPOSITETEMPLATE Composite[2];
+ ULONG refComposite[2];
+ SDCAXU_DATA SdcaXuData;
+
+} CODEC_DEVICE_CONTEXT, *PCODEC_DEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_DEVICE_CONTEXT, GetCodecDeviceContext)
+
+//
+// Define RENDER device context.
+//
+typedef struct _CODEC_RENDER_DEVICE_CONTEXT {
+ ACXCIRCUIT Circuit;
+ BOOLEAN FirstTimePrepareHardware;
+} CODEC_RENDER_DEVICE_CONTEXT, *PCODEC_RENDER_DEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_RENDER_DEVICE_CONTEXT, GetRenderDeviceContext)
+
+//
+// Define RENDER circuit context.
+//
+typedef struct _CODEC_RENDER_CIRCUIT_CONTEXT {
+ ACXMUTE MuteElement;
+ ACXVOLUME VolumeElement;
+} CODEC_RENDER_CIRCUIT_CONTEXT, *PCODEC_RENDER_CIRCUIT_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_RENDER_CIRCUIT_CONTEXT, GetRenderCircuitContext)
+
+//
+// Define CAPTURE device context.
+//
+typedef struct _CODEC_CAPTURE_DEVICE_CONTEXT {
+ ACXCIRCUIT Circuit;
+ BOOLEAN FirstTimePrepareHardware;
+} CODEC_CAPTURE_DEVICE_CONTEXT, *PCODEC_CAPTURE_DEVICE_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_CAPTURE_DEVICE_CONTEXT, GetCaptureDeviceContext)
+
+//
+// Define CAPTURE circuit context.
+//
+typedef struct _CODEC_CAPTURE_CIRCUIT_CONTEXT {
+ BOOLEAN KwsActiveVadStream;
+ KEVENT KwsSuspendEvent;
+ KEVENT KwsResumeEvent;
+ ACXDATAFORMAT KwsDataFormat;
+} CODEC_CAPTURE_CIRCUIT_CONTEXT, *PCODEC_CAPTURE_CIRCUIT_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_CAPTURE_CIRCUIT_CONTEXT, GetCaptureCircuitContext)
+
+//
+// Define CODEC render/capture stream context.
+//
+typedef struct _CODEC_STREAM_CONTEXT {
+ PVOID StreamEngine;
+} CODEC_STREAM_CONTEXT, *PCODEC_STREAM_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_STREAM_CONTEXT, GetCodecStreamContext)
+
+//
+// Define CODEC circuit/stream element context.
+//
+typedef struct _CODEC_ELEMENT_CONTEXT {
+ BOOLEAN Dummy;
+} CODEC_ELEMENT_CONTEXT, *PCODEC_ELEMENT_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_ELEMENT_CONTEXT, GetCodecElementContext)
+
+//
+// Define CODEC circuit/stream element context.
+//
+typedef struct _CODEC_MUTE_ELEMENT_CONTEXT {
+ BOOL MuteState[MAX_CHANNELS];
+ WDFTIMER Timer; // for testing only.
+} CODEC_MUTE_ELEMENT_CONTEXT, *PCODEC_MUTE_ELEMENT_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_MUTE_ELEMENT_CONTEXT, GetCodecMuteElementContext)
+
+//
+// Define CODEC mute timer context.
+//
+typedef struct _CODEC_MUTE_TIMER_CONTEXT {
+ ACXMUTE MuteElement;
+} CODEC_MUTE_TIMER_CONTEXT, *PCODEC_MUTE_TIMER_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_MUTE_TIMER_CONTEXT, GetCodecMuteTimerContext)
+
+//
+// Define CODEC circuit/stream element context.
+//
+typedef struct _CODEC_VOLUME_ELEMENT_CONTEXT {
+ LONG VolumeLevel[MAX_CHANNELS];
+ WDFTIMER Timer; // for testing only.
+} CODEC_VOLUME_ELEMENT_CONTEXT, *PCODEC_VOLUME_ELEMENT_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_VOLUME_ELEMENT_CONTEXT, GetCodecVolumeElementContext)
+
+
+#define VOLUME_STEPPING 0x8000
+#define VOLUME_LEVEL_MAXIMUM 0x00000000
+#define VOLUME_LEVEL_MINIMUM (-96 * 0x10000)
+
+//
+// Define CODEC mute timer context.
+//
+typedef struct _CODEC_VOLUME_TIMER_CONTEXT {
+ ACXVOLUME VolumeElement;
+} CODEC_VOLUME_TIMER_CONTEXT, *PCODEC_VOLUME_TIMER_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_VOLUME_TIMER_CONTEXT, GetCodecVolumeTimerContext)
+
+
+//
+// Define CODEC format context.
+//
+typedef struct _CODEC_FORMAT_CONTEXT {
+ BOOLEAN Dummy;
+} CODEC_FORMAT_CONTEXT, *PCODEC_FORMAT_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_FORMAT_CONTEXT, GetCodecFormatContext)
+
+typedef struct _CODEC_PIN_CONTEXT {
+ BOOLEAN Dummy;
+} CODEC_PIN_CONTEXT, *PCODEC_PIN_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_PIN_CONTEXT, GetCodecPinContext)
+
+typedef struct _CODEC_JACK_CONTEXT
+{
+ ULONG Dummy;
+} CODEC_JACK_CONTEXT, *PCODEC_JACK_CONTEXT;
+
+WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(CODEC_JACK_CONTEXT, GetCodecJackContext)
+
+typedef enum {
+ CompositeType_RENDER,
+ CompositeType_CAPTURE
+}CompositeType;
+
+//
+// Driver prototypes.
+//
+DRIVER_INITIALIZE DriverEntry;
+EVT_WDF_DRIVER_UNLOAD Codec_DriverUnload;
+EVT_WDF_DRIVER_DEVICE_ADD Codec_EvtBusDeviceAdd;
+
+// Device callbacks.
+
+EVT_WDF_DEVICE_PREPARE_HARDWARE Codec_EvtDevicePrepareHardware;
+EVT_WDF_DEVICE_RELEASE_HARDWARE Codec_EvtDeviceReleaseHardware;
+EVT_WDF_DEVICE_CONTEXT_CLEANUP Codec_EvtDeviceContextCleanup;
+
+// Stream callbacks shared between Capture and Render
+
+EVT_WDF_OBJECT_CONTEXT_DESTROY Codec_EvtStreamDestroy;
+EVT_ACX_STREAM_GET_HW_LATENCY Codec_EvtStreamGetHwLatency;
+EVT_ACX_STREAM_PREPARE_HARDWARE Codec_EvtStreamPrepareHardware;
+EVT_ACX_STREAM_RELEASE_HARDWARE Codec_EvtStreamReleaseHardware;
+EVT_ACX_STREAM_RUN Codec_EvtStreamRun;
+EVT_ACX_STREAM_PAUSE Codec_EvtStreamPause;
+EVT_ACX_STREAM_ASSIGN_DRM_CONTENT_ID Codec_EvtStreamAssignDrmContentId;
+
+// Render callbacks.
+
+EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecR_EvtCircuitRequestPreprocess;
+EVT_ACX_CIRCUIT_CREATE_STREAM CodecR_EvtCircuitCreateStream;
+EVT_ACX_CIRCUIT_POWER_UP CodecR_EvtCircuitPowerUp;
+EVT_ACX_CIRCUIT_POWER_DOWN CodecR_EvtCircuitPowerDown;
+EVT_ACX_STREAM_SET_RENDER_PACKET CodecR_EvtStreamSetRenderPacket;
+EVT_ACX_PIN_SET_DATAFORMAT CodecR_EvtAcxPinSetDataFormat;
+EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecR_EvtPinContextCleanup;
+
+EVT_ACX_CIRCUIT_COMPOSITE_CIRCUIT_INITIALIZE CodecR_EvtCircuitCompositeCircuitInitialize;
+EVT_ACX_CIRCUIT_COMPOSITE_INITIALIZE CodecR_EvtCircuitCompositeInitialize;
+
+// Capture callbacks.
+
+EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecC_EvtCircuitRequestPreprocess;
+EVT_ACX_CIRCUIT_CREATE_STREAM CodecC_EvtCircuitCreateStream;
+EVT_ACX_CIRCUIT_POWER_UP CodecC_EvtCircuitPowerUp;
+EVT_ACX_CIRCUIT_POWER_DOWN CodecC_EvtCircuitPowerDown;
+EVT_ACX_STREAM_GET_CAPTURE_PACKET CodecC_EvtStreamGetCapturePacket;
+EVT_ACX_PIN_SET_DATAFORMAT CodecC_EvtAcxPinSetDataFormat;
+EVT_WDF_DEVICE_CONTEXT_CLEANUP CodecC_EvtPinContextCleanup;
+
+EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecC_EvtStreamRequestPreprocess;
+
+EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitDeviceKwsCapability;
+EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitVadCapability;
+EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitVadEntities;
+EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitSetKwsAccessEvents;
+EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitConfigureVadPort;
+EVT_ACX_OBJECT_PROCESS_REQUEST CodecC_EvtCircuitCleanupVadPort;
+
+EVT_ACX_MUTE_ASSIGN_STATE CodecR_EvtMuteAssignStateCallback;
+EVT_ACX_MUTE_RETRIEVE_STATE CodecR_EvtMuteRetrieveStateCallback;
+EVT_WDF_TIMER CodecR_EvtMuteTimerFunc;
+EVT_ACX_VOLUME_ASSIGN_LEVEL CodecR_EvtVolumeAssignLevelCallback;
+EVT_ACX_VOLUME_RETRIEVE_LEVEL CodecR_EvtVolumeRetrieveLevelCallback;
+EVT_WDF_TIMER CodecR_EvtVolumeTimerFunc;
+EVT_ACX_OBJECT_PREPROCESS_REQUEST CodecR_EvtStreamRequestPreprocess;
+
+/* make internal prototypes usable from C++ */
+#ifdef __cplusplus
+}
+#endif
+
+//
+// Used to store the registry settings path for the driver
+//
+extern UNICODE_STRING g_RegistryPath;
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+CopyRegistrySettingsPath(
+ _In_ PUNICODE_STRING RegistryPath
+ );
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+Codec_AddComposites(_In_ WDFDEVICE Device, _In_ CompositeType compositeType);
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+Codec_AddRenderComposites(_In_ WDFDEVICE Device);
+
+__drv_requiresIRQL(PASSIVE_LEVEL)
+PAGED_CODE_SEG
+NTSTATUS
+Codec_AddCaptureComposites(_In_ WDFDEVICE Device);
+
+#pragma code_seg()
+NTSTATUS
+Codec_RemoveComposites(_In_ WDFDEVICE Device);
+
+PAGED_CODE_SEG
+NTSTATUS
+Codec_SetPowerPolicy(
+ _In_ WDFDEVICE Device
+ );
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_AddRenders(
+ _In_ WDFDRIVER Driver,
+ _In_ WDFDEVICE Device
+ );
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_AddStaticRender(
+ _In_ WDFDEVICE Device
+ );
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_CreateRenderCircuit(
+ _In_ WDFDEVICE Device,
+ _Out_ ACXCIRCUIT * Circuit
+ );
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_AddCaptures(
+ _In_ WDFDRIVER Driver,
+ _In_ WDFDEVICE Device
+ );
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_AddStaticCapture(
+ _In_ WDFDEVICE Device
+ );
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecC_CreateCaptureCircuit(
+ _In_ WDFDEVICE Device,
+ _Out_ ACXCIRCUIT * Circuit
+ );
+
+//
+// Extension Unit
+//
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetJackOverride
+(
+ _In_ PVOID Context, // SDCA Context
+ _In_ BOOLEAN Override // TRUE: Override
+ // FALSE: Default SDCA behavior
+);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetJackSelectedMode
+(
+ _In_ PVOID Context, // SDCA Context
+ _In_ ULONG GroupEntityId, // SDCA Group Entity ID for Jack(s)
+ _In_ ULONG SelectedMode // Type of jack type overriden by XU
+);
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuPDEPowerReferenceAcquire
+(
+ _In_ PVOID Context,
+ _In_ ULONG PowerDomainEntityId,
+ _In_ SDCAXU_POWER_STATE RequiredState
+);
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuPDEPowerReferenceRelease
+(
+ _In_ PVOID Context,
+ _In_ ULONG PowerDomainEntityId,
+ _In_ SDCAXU_POWER_STATE ReleasedState
+);
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuReadDeferredAudioControls
+(
+ _In_ PVOID Context,
+ _Inout_ PSDCA_AUDIO_CONTROLS Controls
+);
+
+#pragma code_seg()
+NTSTATUS Codec_SdcaXuWriteDeferredAudioControls
+(
+ _In_ PVOID Context,
+ _Inout_ PSDCA_AUDIO_CONTROLS Controls
+);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetXUEntities
+(
+ _In_ PVOID Context,
+ _In_ ULONG NumEntities,
+ _In_reads_(NumEntities)
+ ULONG EntityIDs[]
+);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuRegisterForInterrupts
+(
+ _In_ PVOID Context,
+ _In_ PSDCAXU_INTERRUPT_INFO InterruptInfo
+);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetRenderEndpointConfig
+(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit
+);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetCaptureEndpointConfig
+(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit
+);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_GetSdcaXu(_In_ WDFDEVICE Device);
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SetSdcaXuHwConfig(_In_ WDFDEVICE Device);
+
+#pragma code_seg()
+
+#endif // _PRIVATE_H_
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp
new file mode 100644
index 00000000..901398dc
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/render.cpp
@@ -0,0 +1,1310 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ Render.cpp
+
+Abstract:
+
+ Contains ACX Capture factory and circuit
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "private.h"
+#include <devguid.h>
+#include "stdunk.h"
+#include <ks.h>
+#include <mmsystem.h>
+#include <ksmedia.h>
+#include "streamengine.h"
+#include "soundwirecontroller.h"
+#include "sdcastreaming.h"
+#include "CircuitHelper.h"
+
+#include "AudioFormats.h"
+
+#ifndef __INTELLISENSE__
+#include "render.tmh"
+#endif
+
+//#define CODEC_NEXT_CIRCUIT_STR L"\\??\\ROOT#AcxAmpTestDriver#0000#{2c6bb644-e1ae-47f8-9a2b-1d1fa750f2fa}\\Speaker0"
+//#define CODEC_NEXT_CIRCUIT_STR L"\\??\\ROOT#AcxAmpTestDriver#0000#{6994AD04-93EF-11D0-A3CC-00A0C9223196}\\Speaker0"
+
+//#define CODEC_PREVIOUS_CIRCUIT_STR L"\\??\\AcxDspTestDriver#DynamicEnumSpeaker0#1&6244bc4&d&00#{2c6bb644-e1ae-47f8-9a2b-1d1fa750f2fa}\\Speaker0"
+//#define CODEC_PREVIOUS_CIRCUIT_STR L"\\??\\AcxDspTestDriver#DynamicEnumSpeaker0#1&6244bc4&0&00#{6994AD04-93EF-11D0-A3CC-00A0C9223196}\\Speaker0"
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPinCInstancesCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+ )
+{
+ PAGED_CODE();
+
+ // TEMP: for testing only.
+ UNREFERENCED_PARAMETER(Object);
+ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPinCTypesCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+ )
+{
+ PAGED_CODE();
+
+ // TEMP: for testing only.
+ UNREFERENCED_PARAMETER(Object);
+ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPinDataFlowCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+ )
+{
+ PAGED_CODE();
+
+ // TEMP: for testing only.
+ UNREFERENCED_PARAMETER(Object);
+ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPinDataRangesCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+ )
+{
+ PAGED_CODE();
+
+ // TEMP: for testing only.
+ UNREFERENCED_PARAMETER(Object);
+ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPinDataIntersectionCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+ )
+{
+ PAGED_CODE();
+
+ // TEMP: for testing only.
+ UNREFERENCED_PARAMETER(Object);
+ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtAcxPinSetDataFormat (
+ _In_ ACXPIN Pin,
+ _In_ ACXDATAFORMAT DataFormat
+ )
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Pin);
+ UNREFERENCED_PARAMETER(DataFormat);
+
+
+ return STATUS_NOT_SUPPORTED;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtMuteAssignStateCallback(
+ _In_ ACXMUTE Mute,
+ _In_ ULONG Channel,
+ _In_ ULONG State
+ )
+{
+ PAGED_CODE();
+
+ ASSERT(Mute);
+ PCODEC_MUTE_ELEMENT_CONTEXT muteCtx = GetCodecMuteElementContext(Mute);
+ ASSERT(muteCtx);
+
+ if (Channel != ALL_CHANNELS_ID)
+ {
+ muteCtx->MuteState[Channel] = State;
+ }
+ else
+ {
+ for (ULONG i = 0; i < MAX_CHANNELS; ++i)
+ {
+ muteCtx->MuteState[i] = State;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+NTAPI
+CodecR_EvtMuteRetrieveStateCallback(
+ _In_ ACXMUTE Mute,
+ _In_ ULONG Channel,
+ _Out_ ULONG *State
+ )
+{
+ PAGED_CODE();
+
+ ASSERT(Mute);
+ PCODEC_MUTE_ELEMENT_CONTEXT muteCtx = GetCodecMuteElementContext(Mute);
+ ASSERT(muteCtx);
+
+ if (Channel == ALL_CHANNELS_ID)
+ {
+ Channel = 0;
+ }
+
+ *State = muteCtx->MuteState[Channel];
+
+ return STATUS_SUCCESS;
+}
+
+//
+// Testing mute element.
+//
+#pragma code_seg()
+VOID
+CodecR_EvtMuteTimerFunc(
+ _In_ WDFTIMER Timer
+ )
+{
+ PCODEC_MUTE_TIMER_CONTEXT timerCtx = GetCodecMuteTimerContext(Timer);
+
+ ASSERT(timerCtx != NULL);
+ ASSERT(timerCtx->MuteElement != NULL);
+
+ PCODEC_MUTE_ELEMENT_CONTEXT muteCtx = GetCodecMuteElementContext(timerCtx->MuteElement);
+ ASSERT(muteCtx != NULL);
+
+ // update settings 0 <-> 1
+ for (ULONG i = 0; i < MAX_CHANNELS; ++i)
+ {
+ muteCtx->MuteState[i] = !muteCtx->MuteState[i];
+ }
+
+ AcxMuteChangeStateNotification(timerCtx->MuteElement);
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtVolumeAssignLevelCallback(
+ _In_ ACXVOLUME Volume,
+ _In_ ULONG Channel,
+ _In_ LONG VolumeLevel
+ )
+{
+ PAGED_CODE();
+
+ ASSERT(Volume);
+ PCODEC_VOLUME_ELEMENT_CONTEXT volumeCtx = GetCodecVolumeElementContext(Volume);
+ ASSERT(volumeCtx);
+
+ if (Channel != ALL_CHANNELS_ID)
+ {
+ volumeCtx->VolumeLevel[Channel] = VolumeLevel;
+ }
+ else
+ {
+ for (ULONG i = 0; i < MAX_CHANNELS; ++i)
+ {
+ volumeCtx->VolumeLevel[i] = VolumeLevel;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+NTAPI
+CodecR_EvtVolumeRetrieveLevelCallback(
+ _In_ ACXVOLUME Volume,
+ _In_ ULONG Channel,
+ _Out_ LONG *VolumeLevel
+ )
+{
+ PAGED_CODE();
+
+ ASSERT(Volume);
+ PCODEC_VOLUME_ELEMENT_CONTEXT volumeCtx = GetCodecVolumeElementContext(Volume);
+ ASSERT(volumeCtx);
+
+ if (Channel == ALL_CHANNELS_ID)
+ {
+ Channel = 0;
+ }
+
+ *VolumeLevel = volumeCtx->VolumeLevel[Channel];
+
+ return STATUS_SUCCESS;
+}
+
+//
+// Testing volume element.
+//
+#pragma code_seg()
+VOID
+CodecR_EvtVolumeTimerFunc(
+ _In_ WDFTIMER Timer
+ )
+{
+ PCODEC_VOLUME_TIMER_CONTEXT timerCtx = GetCodecVolumeTimerContext(Timer);
+
+ ASSERT(timerCtx != NULL);
+ ASSERT(timerCtx->VolumeElement != NULL);
+
+ PCODEC_VOLUME_ELEMENT_CONTEXT volumeCtx = GetCodecVolumeElementContext(timerCtx->VolumeElement);
+ ASSERT(volumeCtx != NULL);
+
+ // Toggle volume between max and min
+ for (ULONG i = 0; i < MAX_CHANNELS; ++i)
+ {
+ volumeCtx->VolumeLevel[i] = volumeCtx->VolumeLevel[i] == VOLUME_LEVEL_MAXIMUM ? VOLUME_LEVEL_MINIMUM : VOLUME_LEVEL_MAXIMUM;
+ }
+
+ AcxVolumeChangeLevelNotification(timerCtx->VolumeElement);
+}
+
+#pragma code_seg()
+VOID
+CodecR_EvtPinContextCleanup(
+ _In_ WDFOBJECT WdfPin
+ )
+/*++
+
+Routine Description:
+
+ In this callback, it cleans up pin context.
+
+Arguments:
+
+ WdfDevice - WDF device object
+
+Return Value:
+
+ NULL
+
+--*/
+{
+ UNREFERENCED_PARAMETER(WdfPin);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtCircuitRequestPreprocess(
+ _In_ ACXOBJECT Object,
+ _In_ ACXCONTEXT DriverContext,
+ _In_ WDFREQUEST Request
+ )
+/*++
+
+Routine Description:
+
+ This function is an example of a preprocess routine.
+
+--*/
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(DriverContext);
+
+ ASSERT(Object != NULL);
+ ASSERT(DriverContext);
+ ASSERT(Request);
+
+
+ //
+ // Just give the request back to ACX.
+ //
+ (VOID)AcxCircuitDispatchAcxRequest((ACXCIRCUIT)Object, Request);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtStreamRequestPreprocess(
+ _In_ ACXOBJECT Object,
+ _In_ ACXCONTEXT DriverContext,
+ _In_ WDFREQUEST Request
+ )
+/*++
+
+Routine Description:
+
+ This function is an example of a preprocess routine.
+
+--*/
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(DriverContext);
+
+ ASSERT(Object != NULL);
+ ASSERT(DriverContext);
+ ASSERT(Request);
+
+
+ //
+ // Just give the request back to ACX.
+ //
+ (VOID)AcxStreamDispatchAcxRequest((ACXSTREAM)Object, Request);
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_AddRenders(
+ _In_ WDFDRIVER Driver,
+ _In_ WDFDEVICE Device
+ )
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Driver);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ //
+ // Add a static render device.
+ //
+ status = CodecR_AddStaticRender(Device);
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_AddStaticRender(
+ _In_ WDFDEVICE Device
+)
+{
+ PAGED_CODE();
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ //
+ // Alloc audio context to current device.
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_DEVICE_CONTEXT);
+ PCODEC_RENDER_DEVICE_CONTEXT renderDevCtx;
+ RETURN_NTSTATUS_IF_FAILED(WdfObjectAllocateContext(Device, &attributes, (PVOID*)&renderDevCtx));
+ ASSERT(renderDevCtx);
+
+ //
+ // Create a render circuit associated with this device.
+ //
+ ACXCIRCUIT renderCircuit = NULL;
+ RETURN_NTSTATUS_IF_FAILED(CodecR_CreateRenderCircuit(Device, &renderCircuit));
+
+ RETURN_NTSTATUS_IF_FAILED(Codec_SdcaXuSetRenderEndpointConfig(Device, renderCircuit));
+
+ devCtx->Render = renderCircuit;
+
+ return status;
+}
+
+EXTERN_C const GUID DECLSPEC_SELECTANY CODEC_CIRCUIT_RENDER_GUID;
+EXTERN_C const GUID DECLSPEC_SELECTANY EXTENSION_CIRCUIT_RENDER_GUID;
+EXTERN_C const GUID DECLSPEC_SELECTANY SYSTEM_CONTAINER_GUID;
+
+PAGED_CODE_SEG
+NTSTATUS Codec_SdcaXuSetRenderEndpointConfig
+(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit
+)
+{
+ PAGED_CODE();
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PCODEC_DEVICE_CONTEXT devCtx;
+ devCtx = GetCodecDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ DECLARE_CONST_UNICODE_STRING(circuitName, L"ExtensionSpeaker0");
+ DECLARE_CONST_UNICODE_STRING(circuitUri, EXT_RENDER_CIRCUIT_URI);
+
+#pragma prefast(suppress:__WARNING_ALIASED_MEMORY_LEAK, "memory is freed by scope_exit")
+ PSDCAXU_ACX_CIRCUIT_CONFIG exCircuitConfig = (PSDCAXU_ACX_CIRCUIT_CONFIG)ExAllocatePool2(
+ POOL_FLAG_NON_PAGED,
+ sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength,
+ DRIVER_TAG);
+ RETURN_NTSTATUS_IF_TRUE(NULL == exCircuitConfig, STATUS_INSUFFICIENT_RESOURCES);
+ auto exConfigFree = scope_exit([&exCircuitConfig]() {
+ ExFreePoolWithTag(exCircuitConfig, DRIVER_TAG);
+ });
+
+ //
+ // Provide circuit configuration to SDCA XU driver
+ // SDCA XU driver will generate circuits to match this configuration
+ //
+ if (devCtx->SdcaXuData.bSdcaXu)
+ {
+ exCircuitConfig->cbSize = sizeof(SDCAXU_ACX_CIRCUIT_CONFIG) + circuitName.MaximumLength;
+
+ exCircuitConfig->CircuitName = circuitName;
+ exCircuitConfig->CircuitName.Buffer = (PWCH)(exCircuitConfig + 1);
+ RtlCopyMemory(exCircuitConfig->CircuitName.Buffer, circuitName.Buffer, circuitName.MaximumLength);
+
+ exCircuitConfig->CircuitContext = Circuit;
+ exCircuitConfig->CircuitType = AcxCircuitTypeRender;
+ exCircuitConfig->ContainerID = SYSTEM_CONTAINER_GUID;
+ exCircuitConfig->ComponentID = EXTENSION_CIRCUIT_RENDER_GUID;
+ exCircuitConfig->ComponentUri = circuitUri;
+
+ PSDCAXU_INTERFACE_V0101 exInterface = &devCtx->SdcaXuData.ExtensionInterface;
+ PVOID exContext = devCtx->SdcaXuData.ExtensionInterface.InterfaceHeader.Context;
+
+ RETURN_NTSTATUS_IF_FAILED(exInterface->EvtSetEndpointConfig(exContext, SdcaXuEndpointConfigTypeAcxCircuitConfig, exCircuitConfig, exCircuitConfig->cbSize));
+ }
+
+ return status;
+}
+
+// {3CE41646-9BF2-4A9E-B851-D711CAE9AEA8}
+DEFINE_GUID(SDCAVADPropsetId,
+ 0x3ce41646, 0x9bf2, 0x4a9e, 0xb8, 0x51, 0xd7, 0x11, 0xca, 0xe9, 0xae, 0xa8);
+
+typedef enum {
+ SDCAVAD_PROPERTY_TEST1,
+ SDCAVAD_PROPERTY_TEST2,
+ SDCAVAD_PROPERTY_TEST3,
+ SDCAVAD_PROPERTY_TEST4,
+ SDCAVAD_PROPERTY_TEST5,
+ SDCAVAD_PROPERTY_TEST6,
+} SDCAVAD_Properties;
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_SDCAVADPropertyTest1(
+ _Inout_ PVOID pValue,
+ _In_ ULONG ValueCb,
+ _Out_ PULONG ValueCbOut
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(pValue);
+ UNREFERENCED_PARAMETER(ValueCb);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST1");
+
+ *ValueCbOut = 0;
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_SDCAVADPropertyTest2(
+ _Inout_ PVOID pValue,
+ _In_ ULONG ValueCb,
+ _Out_ PULONG ValueCbOut
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(ValueCb);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST2");
+
+ *((PULONG)pValue) = 10;
+ *ValueCbOut = sizeof(ULONG);
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_SDCAVADPropertyTest5(
+ _Inout_ PVOID pValue,
+ _In_ ULONG ValueCb,
+ _Out_ PULONG ValueCbOut
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(pValue);
+ UNREFERENCED_PARAMETER(ValueCb);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST5");
+
+ *ValueCbOut = 0;
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_SDCAVADPropertyTest6(
+ _Inout_ PVOID pValue,
+ _In_ ULONG ValueCb,
+ _Out_ PULONG ValueCbOut
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(ValueCb);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: SDCAVAD_PROPERTY_TEST6");
+
+ *((PULONG)pValue) = 12;
+ *ValueCbOut = sizeof(ULONG);
+
+ return status;
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPropertyCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Object);
+
+ ACX_REQUEST_PARAMETERS params;
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+
+ AcxRequestGetParameters(Request, &params);
+
+ NTSTATUS status = STATUS_SUCCESS;
+ PVOID Value = params.Parameters.Property.Value;
+ ULONG ValueCb = params.Parameters.Property.ValueCb;
+ ULONG ValueCbOut = 0;
+
+ switch (params.Parameters.Property.Id)
+ {
+ case SDCAVAD_PROPERTY_TEST1:
+ status = CodecR_SDCAVADPropertyTest1(Value, ValueCb, &ValueCbOut);
+ break;
+ case SDCAVAD_PROPERTY_TEST2:
+ status = CodecR_SDCAVADPropertyTest2(Value, ValueCb, &ValueCbOut);
+ break;
+ case SDCAVAD_PROPERTY_TEST5:
+ status = CodecR_SDCAVADPropertyTest5(Value, ValueCb, &ValueCbOut);
+ break;
+ case SDCAVAD_PROPERTY_TEST6:
+ status = CodecR_SDCAVADPropertyTest6(Value, ValueCb, &ValueCbOut);
+ break;
+ default:
+ break;
+ }
+
+ WdfRequestCompleteWithInformation(Request, status, ValueCbOut);
+}
+
+PAGED_CODE_SEG
+VOID
+CodecR_EvtPropertyVendorSpecificCallback(
+ _In_ WDFOBJECT Object,
+ _In_ WDFREQUEST Request
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Object);
+
+ ACX_REQUEST_PARAMETERS params;
+ ACX_REQUEST_PARAMETERS_INIT(&params);
+
+ AcxRequestGetParameters(Request, &params);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ // The Class Driver will send IOCTL_SOUNDWIRE_VENDOR_SPECIFIC with Control/Value to the SoundWire Controller.
+
+ PVIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL control = (PVIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL)params.Parameters.Property.Control;
+ ULONG controlCb = params.Parameters.Property.ControlCb;
+
+ PVIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA value = (PVIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA)params.Parameters.Property.Value;
+ ULONG valueCb = params.Parameters.Property.ValueCb;
+
+ ULONG_PTR information = 0;
+
+ // Validate we have enough control data
+ if (controlCb < sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL))
+ {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ else if (control->VendorSpecificSize != sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_CONTROL))
+ {
+ status = STATUS_INVALID_PARAMETER;
+ }
+ else if (control->VendorSpecificId == VirtualStackVendorSpecificRequestGetTestData)
+ {
+ if (valueCb == 0 && value == nullptr)
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ information = sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA);
+ }
+ else if (valueCb < sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ value->Test1 = 0x12345678;
+ value->Test2 = 0x87654321;
+ information = sizeof(VIRTUAL_STACK_VENDOR_SPECIFIC_VALUE_TEST_DATA);
+ }
+ }
+ else if (control->VendorSpecificId == VirtualStackVendorSpecificRequestSetTestConfig)
+ {
+ DrvLogInfo(g_SDCAVCodecLog, FLAG_STREAM, L"SDCAVCodec: VENDOR SPECIFIC Set Test Config %d", control->Config.IsScatterGather);
+ }
+ else
+ {
+ status = STATUS_INVALID_PARAMETER;
+ }
+
+ WdfRequestCompleteWithInformation(Request, status, information);
+}
+
+static ACX_PROPERTY_ITEM g_CircuitProperties[] =
+{
+ {
+ &SDCAVADPropsetId,
+ SDCAVAD_PROPERTY_TEST1,
+ ACX_PROPERTY_ITEM_FLAG_SET,
+ CodecR_EvtPropertyCallback
+ },
+ {
+ &SDCAVADPropsetId,
+ SDCAVAD_PROPERTY_TEST2,
+ ACX_PROPERTY_ITEM_FLAG_GET,
+ CodecR_EvtPropertyCallback
+ },
+ {
+ &SDCAVADPropsetId,
+ SDCAVAD_PROPERTY_TEST5,
+ ACX_PROPERTY_ITEM_FLAG_SET,
+ CodecR_EvtPropertyCallback
+ },
+ {
+ &SDCAVADPropsetId,
+ SDCAVAD_PROPERTY_TEST6,
+ ACX_PROPERTY_ITEM_FLAG_GET,
+ CodecR_EvtPropertyCallback
+ },
+ {
+ &KSPROPERTYSETID_Sdca,
+ KSPROPERTY_SDCA_VENDOR_SPECIFIC,
+ ACX_PROPERTY_ITEM_FLAG_GET | ACX_PROPERTY_ITEM_FLAG_SET,
+ CodecR_EvtPropertyVendorSpecificCallback
+ },
+};
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_CreateRenderCircuit(
+ _In_ WDFDEVICE Device,
+ _Out_ ACXCIRCUIT * Circuit
+)
+/*++
+
+Routine Description:
+
+ This routine builds the CODEC render circuit.
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ //
+ // Get a CircuitInit structure.
+ //
+ PACXCIRCUIT_INIT circuitInit = NULL;
+ circuitInit = AcxCircuitInitAllocate(Device);
+ RETURN_NTSTATUS_IF_TRUE(NULL == circuitInit, STATUS_NO_MEMORY);
+ auto circuitInitScope = scope_exit([&circuitInit]() {
+ AcxCircuitInitFree(circuitInit);
+ });
+
+ //
+ // Init output value.
+ //
+ *Circuit = NULL;
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Create a circuit.
+ //
+
+ //
+ // Add circuit identifiers.
+ //
+ AcxCircuitInitSetComponentId(circuitInit, &CODEC_CIRCUIT_RENDER_GUID);
+
+ DECLARE_CONST_UNICODE_STRING(circuitUri, RENDER_CIRCUIT_URI);
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignComponentUri(circuitInit, &circuitUri));
+
+ WDF_OBJECT_ATTRIBUTES attributes;
+ ACXCIRCUIT circuit;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_RENDER_CIRCUIT_CONTEXT);
+ DECLARE_CONST_UNICODE_STRING(circuitName, L"Speaker0");
+
+ //
+ // Add properties, events and methods.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitInitAssignProperties(circuitInit,
+ g_CircuitProperties,
+ SIZEOF_ARRAY(g_CircuitProperties)));
+
+
+ RETURN_NTSTATUS_IF_FAILED(CreateRenderCircuit(circuitInit, circuitName, Device, &circuit));
+ circuitInitScope.release();
+
+ CODEC_RENDER_CIRCUIT_CONTEXT *circuitCtx;
+ ASSERT(circuit != NULL);
+ circuitCtx = GetRenderCircuitContext(circuit);
+ ASSERT(circuitCtx);
+
+ //
+ // Post circuit creation initialization.
+ //
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Add two custom circuit elements. Note that driver doesn't need to
+ // perform this step if it doesn't want to expose any circuit elements.
+ //
+
+ //
+ // Create 1st custom circuit-element (mute element).
+ //
+ ACX_MUTE_CALLBACKS muteCallbacks;
+ ACX_MUTE_CALLBACKS_INIT(&muteCallbacks);
+ muteCallbacks.EvtAcxMuteAssignState = CodecR_EvtMuteAssignStateCallback;
+ muteCallbacks.EvtAcxMuteRetrieveState = CodecR_EvtMuteRetrieveStateCallback;
+
+ ACX_MUTE_CONFIG muteCfg;
+ ACX_MUTE_CONFIG_INIT(&muteCfg);
+ muteCfg.ChannelsCount = MAX_CHANNELS;
+ muteCfg.Callbacks = &muteCallbacks;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_MUTE_ELEMENT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ const int numElements = 2;
+ ACXELEMENT elements[numElements] = {0};
+ RETURN_NTSTATUS_IF_FAILED(AcxMuteCreate(circuit, &attributes, &muteCfg, (ACXMUTE *)&elements[0]));
+
+ ASSERT(elements[0] != NULL);
+ CODEC_MUTE_ELEMENT_CONTEXT *muteCtx;
+ muteCtx = GetCodecMuteElementContext(elements[0]);
+ ASSERT(muteCtx);
+ UNREFERENCED_PARAMETER(muteCtx);
+
+ circuitCtx->MuteElement = (ACXMUTE)elements[0];
+
+ //
+ // Testing async mute state change.
+ //
+ {
+ WDF_TIMER_CONFIG timerCfg;
+ PCODEC_MUTE_TIMER_CONTEXT timerCtx;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_MUTE_TIMER_CONTEXT);
+ attributes.ParentObject = circuitCtx->MuteElement;
+
+ WDF_TIMER_CONFIG_INIT_PERIODIC(&timerCfg, CodecR_EvtMuteTimerFunc, 4000 /* 4sec in msec */);
+
+ RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate(&timerCfg, &attributes, &muteCtx->Timer));
+
+ ASSERT(muteCtx->Timer);
+
+ timerCtx = GetCodecMuteTimerContext(muteCtx->Timer);
+ ASSERT(timerCtx);
+
+ timerCtx->MuteElement = circuitCtx->MuteElement;
+ }
+
+ //
+ // Create 2nd custom circuit-element (volume element).
+ //
+ ACX_VOLUME_CALLBACKS volumeCallbacks;
+ ACX_VOLUME_CALLBACKS_INIT(&volumeCallbacks);
+ volumeCallbacks.EvtAcxVolumeAssignLevel = CodecR_EvtVolumeAssignLevelCallback;
+ volumeCallbacks.EvtAcxVolumeRetrieveLevel = CodecR_EvtVolumeRetrieveLevelCallback;
+
+ ACX_VOLUME_CONFIG volumeCfg;
+ ACX_VOLUME_CONFIG_INIT(&volumeCfg);
+ volumeCfg.ChannelsCount = MAX_CHANNELS;
+ volumeCfg.Minimum = VOLUME_LEVEL_MINIMUM;
+ volumeCfg.Maximum = VOLUME_LEVEL_MAXIMUM;
+ volumeCfg.SteppingDelta = VOLUME_STEPPING;
+ volumeCfg.Callbacks = &volumeCallbacks;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_VOLUME_ELEMENT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxVolumeCreate(circuit, &attributes, &volumeCfg, (ACXVOLUME *)&elements[1]));
+
+ ASSERT(elements[1] != NULL);
+ CODEC_VOLUME_ELEMENT_CONTEXT *volumeCtx;
+ volumeCtx = GetCodecVolumeElementContext(elements[1]);
+ ASSERT(volumeCtx);
+ volumeCtx->VolumeLevel[0] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING;
+ volumeCtx->VolumeLevel[1] = (VOLUME_LEVEL_MAXIMUM + VOLUME_LEVEL_MINIMUM) / 2 / VOLUME_STEPPING * VOLUME_STEPPING;
+
+ circuitCtx->VolumeElement = (ACXVOLUME)elements[1];
+
+ //
+ // Testing async volume state change.
+ //
+ {
+ WDF_TIMER_CONFIG timerCfg;
+ PCODEC_VOLUME_TIMER_CONTEXT timerCtx;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_VOLUME_TIMER_CONTEXT);
+ attributes.ParentObject = circuitCtx->VolumeElement;
+
+ WDF_TIMER_CONFIG_INIT_PERIODIC(&timerCfg, CodecR_EvtVolumeTimerFunc, 4500 /* 4.5sec in msec */);
+
+ RETURN_NTSTATUS_IF_FAILED(WdfTimerCreate(&timerCfg, &attributes, &volumeCtx->Timer));
+
+ ASSERT(volumeCtx->Timer);
+
+ timerCtx = GetCodecVolumeTimerContext(volumeCtx->Timer);
+ ASSERT(timerCtx);
+
+ timerCtx->VolumeElement = circuitCtx->VolumeElement;
+ }
+
+ //
+ // Add the circuit elements
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddElements(circuit, elements, SIZEOF_ARRAY(elements)));
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Allocate the formats this circuit supports.
+ //
+ // PCM:44100 channel:2 24in32
+ ACX_DATAFORMAT_CONFIG formatCfg;
+ ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm44100c2_24in32);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ ACXDATAFORMAT formatPcm44100c2_24in32;
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm44100c2_24in32));
+
+ CODEC_FORMAT_CONTEXT *formatCtx;
+ formatCtx = GetCodecFormatContext(formatPcm44100c2_24in32);
+ ASSERT(formatCtx);
+
+ UNREFERENCED_PARAMETER(formatCtx);
+
+ // PCM:48000 channel:2 24in32
+ ACX_DATAFORMAT_CONFIG_INIT_KS(&formatCfg, &Pcm48000c2_24in32);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_FORMAT_CONTEXT);
+ attributes.ParentObject = circuit;
+
+ ACXDATAFORMAT formatPcm48000c2_24in32;
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatCreate(Device, &attributes, &formatCfg, &formatPcm48000c2_24in32));
+
+ formatCtx = GetCodecFormatContext(formatPcm48000c2_24in32);
+ ASSERT(formatCtx);
+ UNREFERENCED_PARAMETER(formatCtx);
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Create render pin. AcxCircuit creates the other pin by default.
+ //
+
+ ACX_PIN_CALLBACKS pinCallbacks;
+ ACX_PIN_CALLBACKS_INIT(&pinCallbacks);
+ pinCallbacks.EvtAcxPinSetDataFormat = CodecR_EvtAcxPinSetDataFormat;
+
+ ACX_PIN_CONFIG pinCfg;
+ ACX_PIN_CONFIG_INIT(&pinCfg);
+ pinCfg.Type = AcxPinTypeSink;
+ pinCfg.Communication = AcxPinCommunicationNone;
+ pinCfg.Category = &KSCATEGORY_AUDIO;
+ pinCfg.PinCallbacks = &pinCallbacks;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT);
+ attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup;
+ attributes.ParentObject = circuit;
+
+ ACXPIN pin;
+ RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin));
+
+ ASSERT(pin != NULL);
+ CODEC_PIN_CONTEXT *pinCtx;
+ pinCtx = GetCodecPinContext(pin);
+ ASSERT(pinCtx);
+
+ //
+ // Add our supported formats to the Default mode for the circuit
+ //
+ ACXDATAFORMATLIST formatList;
+ formatList = AcxPinGetRawDataFormatList(pin);
+ if (formatList == NULL)
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RETURN_NTSTATUS_IF_FAILED(status);
+
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAssignDefaultDataFormat(formatList, formatPcm48000c2_24in32));
+ RETURN_NTSTATUS_IF_FAILED(AcxDataFormatListAddDataFormat(formatList, formatPcm44100c2_24in32));
+
+ // Add render pin, using default pin id (0)
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1));
+
+ ///////////////////////////////////////////////////////////
+ //
+ // Create Bridge Pin.
+ //
+
+ ACX_PIN_CONFIG_INIT(&pinCfg);
+ pinCfg.Type = AcxPinTypeSource;
+ pinCfg.Communication = AcxPinCommunicationNone;
+ pinCfg.Category = &KSNODETYPE_SPEAKER;
+
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_PIN_CONTEXT);
+ attributes.EvtCleanupCallback = CodecR_EvtPinContextCleanup;
+ attributes.ParentObject = circuit;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxPinCreate(circuit, &attributes, &pinCfg, &pin));
+
+ ASSERT(pin != NULL);
+ pinCtx = GetCodecPinContext(pin);
+ ASSERT(pinCtx);
+
+ RETURN_NTSTATUS_IF_FAILED(AddJack(attributes, pin, SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT, RGB(0, 0, 0), AcxConnTypeAtapiInternal, AcxGeoLocFront, AcxGenLocPrimaryBox, AcxPortConnIntegratedDevice));
+
+ // Add render bridge pin
+ RETURN_NTSTATUS_IF_FAILED(AcxCircuitAddPins(circuit, &pin, 1));
+
+ ConnectRenderCircuitElements(numElements, elements, circuit);
+
+ //
+ // Set output value.
+ //
+ *Circuit = circuit;
+
+ //
+ // Done.
+ //
+ status = STATUS_SUCCESS;
+
+
+ return status;
+}
+
+_Use_decl_annotations_
+#pragma code_seg()
+NTSTATUS
+CodecR_EvtCircuitPowerUp (
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ WDF_POWER_DEVICE_STATE PreviousState
+ )
+{
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(PreviousState);
+
+ CODEC_RENDER_CIRCUIT_CONTEXT * circuitCtx;
+ CODEC_MUTE_ELEMENT_CONTEXT * muteCtx;
+ CODEC_VOLUME_ELEMENT_CONTEXT * volumeCtx;
+
+ // for testing.
+ circuitCtx = GetRenderCircuitContext(Circuit);
+ ASSERT(circuitCtx);
+
+ ASSERT(circuitCtx->MuteElement);
+ muteCtx = GetCodecMuteElementContext(circuitCtx->MuteElement);
+ ASSERT(muteCtx);
+
+ ASSERT(circuitCtx->VolumeElement);
+ volumeCtx = GetCodecVolumeElementContext(circuitCtx->VolumeElement);
+ ASSERT(volumeCtx);
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtCircuitPowerDown (
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ WDF_POWER_DEVICE_STATE TargetState
+ )
+{
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(TargetState);
+
+ CODEC_RENDER_CIRCUIT_CONTEXT * circuitCtx;
+ CODEC_MUTE_ELEMENT_CONTEXT * muteCtx;
+ CODEC_VOLUME_ELEMENT_CONTEXT * volumeCtx;
+
+ PAGED_CODE();
+
+ // for testing.
+ circuitCtx = GetRenderCircuitContext(Circuit);
+ ASSERT(circuitCtx);
+
+ ASSERT(circuitCtx->MuteElement);
+ muteCtx = GetCodecMuteElementContext(circuitCtx->MuteElement);
+ ASSERT(muteCtx);
+
+ ASSERT(circuitCtx->VolumeElement);
+ volumeCtx = GetCodecVolumeElementContext(circuitCtx->VolumeElement);
+ ASSERT(volumeCtx);
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtCircuitCompositeCircuitInitialize(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_opt_ ACXOBJECTBAG CircuitProperties
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(Circuit);
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (CircuitProperties != NULL)
+ {
+ DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4);
+ ULONG testUI4 = 0;
+
+ status = AcxObjectBagRetrieveUI4(CircuitProperties, &TestUI4, &testUI4);
+ }
+
+ return status;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtCircuitCompositeInitialize(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ ACXOBJECTBAG CompositeProperties
+ )
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ UNREFERENCED_PARAMETER(Device);
+ UNREFERENCED_PARAMETER(Circuit);
+
+ ASSERT(CompositeProperties);
+
+ DECLARE_CONST_ACXOBJECTBAG_SYSTEM_PROPERTY_NAME(UniqueID);
+ GUID uniqueId = {0};
+ status = AcxObjectBagRetrieveGuid(CompositeProperties, &UniqueID, &uniqueId);
+
+ return status;
+}
+
+PAGED_CODE_SEG
+NTSTATUS
+CodecR_EvtCircuitCreateStream(
+ _In_ WDFDEVICE Device,
+ _In_ ACXCIRCUIT Circuit,
+ _In_ ACXPIN Pin,
+ _In_ PACXSTREAM_INIT StreamInit,
+ _In_ ACXDATAFORMAT StreamFormat,
+ _In_ const GUID * SignalProcessingMode,
+ _In_ ACXOBJECTBAG VarArguments
+)
+/*++
+
+Routine Description:
+
+ This routine create a stream for the specified circuit.
+
+Return Value:
+
+ NT status value
+
+--*/
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ DrvLogEnter(g_SDCAVCodecLog);
+
+ UNREFERENCED_PARAMETER(Pin);
+ UNREFERENCED_PARAMETER(SignalProcessingMode);
+
+ ASSERT(IsEqualGUID(*SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW));
+
+ PCODEC_RENDER_DEVICE_CONTEXT devCtx;
+ devCtx = GetRenderDeviceContext(Device);
+ ASSERT(devCtx != NULL);
+
+ DECLARE_CONST_ACXOBJECTBAG_DRIVER_PROPERTY_NAME(msft, TestUI4);
+ if (VarArguments)
+ {
+ // Get the variable arguments parameter and retrive the values set by the DSP object.
+ ULONG ui4Value = 0;
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagRetrieveUI4(VarArguments, &TestUI4, &ui4Value));
+
+ RETURN_NTSTATUS_IF_TRUE(ui4Value == 0, STATUS_UNSUCCESSFUL);
+
+ ui4Value++;
+
+ // Add the modified value back to object bag.
+ RETURN_NTSTATUS_IF_FAILED(AcxObjectBagAddUI4(VarArguments, &TestUI4, ui4Value));
+ }
+
+ //
+ // Set circuit-callbacks.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxRequestPreprocessCallback(
+ StreamInit,
+ CodecR_EvtStreamRequestPreprocess,
+ (ACXCONTEXT)AcxRequestTypeAny, // dbg only
+ AcxRequestTypeAny,
+ NULL,
+ AcxItemIdNone));
+
+ /*
+ //
+ // Add properties, events and methods.
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignProperties(StreamInit,
+ StreamProperties,
+ StreamPropertiesCount));
+ */
+
+ //
+ // Init streaming callbacks.
+ //
+ ACX_STREAM_CALLBACKS streamCallbacks;
+ ACX_STREAM_CALLBACKS_INIT(&streamCallbacks);
+ streamCallbacks.EvtAcxStreamPrepareHardware = Codec_EvtStreamPrepareHardware;
+ streamCallbacks.EvtAcxStreamReleaseHardware = Codec_EvtStreamReleaseHardware;
+ streamCallbacks.EvtAcxStreamRun = Codec_EvtStreamRun;
+ streamCallbacks.EvtAcxStreamPause = Codec_EvtStreamPause;
+ streamCallbacks.EvtAcxStreamAssignDrmContentId = Codec_EvtStreamAssignDrmContentId;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamInitAssignAcxStreamCallbacks(StreamInit, &streamCallbacks));
+
+ //
+ // Create the stream.
+ //
+ WDF_OBJECT_ATTRIBUTES attributes;
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_STREAM_CONTEXT);
+ attributes.EvtDestroyCallback = Codec_EvtStreamDestroy;
+ ACXSTREAM stream;
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamCreate(Device, Circuit, &attributes, &StreamInit, &stream));
+
+ CRenderStreamEngine *streamEngine = NULL;
+ streamEngine = new(POOL_FLAG_NON_PAGED, DRIVER_TAG) CRenderStreamEngine(stream, StreamFormat);
+ RETURN_NTSTATUS_IF_TRUE(NULL == streamEngine, STATUS_INSUFFICIENT_RESOURCES);
+
+ CODEC_STREAM_CONTEXT *streamCtx;
+ streamCtx = GetCodecStreamContext(stream);
+ ASSERT(streamCtx);
+ streamCtx->StreamEngine = (PVOID)streamEngine;
+ streamEngine = NULL;
+
+ //
+ // Post stream creation initialization.
+ //
+
+ //
+ // Create 1st custom stream-elements.
+ //
+ ACX_ELEMENT_CONFIG elementCfg;
+ ACX_ELEMENT_CONFIG_INIT(&elementCfg);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT);
+ attributes.ParentObject = stream;
+
+ ACXELEMENT elements[2] = {0};
+ RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[0]));
+
+ ASSERT(elements[0] != NULL);
+ CODEC_ELEMENT_CONTEXT *elementCtx;
+ elementCtx = GetCodecElementContext(elements[0]);
+ ASSERT(elementCtx);
+ UNREFERENCED_PARAMETER(elementCtx);
+
+ //
+ // Create 2nd custom stream-elements.
+ //
+ ACX_ELEMENT_CONFIG_INIT(&elementCfg);
+ WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, CODEC_ELEMENT_CONTEXT);
+ attributes.ParentObject = stream;
+
+ RETURN_NTSTATUS_IF_FAILED(AcxElementCreate(stream, &attributes, &elementCfg, &elements[1]));
+
+ ASSERT(elements[1] != NULL);
+ elementCtx = GetCodecElementContext(elements[1]);
+ ASSERT(elementCtx);
+ UNREFERENCED_PARAMETER(elementCtx);
+
+ //
+ // Add stream elements
+ //
+ RETURN_NTSTATUS_IF_FAILED(AcxStreamAddElements(stream, elements, SIZEOF_ARRAY(elements)));
+
+ return status;
+}
+
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc
new file mode 100644
index 00000000..0b1f9749
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/resources.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR "ACX v1.0 Codec Audio Driver"
+#define VER_INTERNALNAME_STR "SDCAVCodec.sys"
+#define VER_ORIGINALFILENAME_STR "SDCAVCodec.sys"
+
+#include "common.ver"
+
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp
new file mode 100644
index 00000000..730f0553
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.cpp
@@ -0,0 +1,270 @@
+/*++
+
+ THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
+ PURPOSE.
+
+Module Name:
+
+ StreamEngine.cpp
+
+Abstract:
+
+ Virtual Streaming Engine - this module controls streaming logic for
+ the device.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "private.h"
+#include <devguid.h>
+#include "stdunk.h"
+#include <ks.h>
+#include <mmsystem.h>
+#include <ksmedia.h>
+#include "streamengine.h"
+
+#ifndef __INTELLISENSE__
+#include "streamengine.tmh"
+#endif
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+CStreamEngine::CStreamEngine(
+ _In_ ACXSTREAM Stream,
+ _In_ ACXDATAFORMAT StreamFormat
+ )
+ : m_CurrentState(AcxStreamStateStop),
+ m_Stream(Stream),
+ m_StreamFormat(StreamFormat)
+{
+ PAGED_CODE();
+
+ KeQueryPerformanceCounter(&m_PerformanceCounterFrequency);
+}
+
+#pragma code_seg()
+CStreamEngine::~CStreamEngine()
+{
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CStreamEngine::PrepareHardware()
+{
+ PAGED_CODE();
+
+ m_CurrentState = AcxStreamStatePause;
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CStreamEngine::ReleaseHardware()
+{
+ PAGED_CODE();
+
+ m_CurrentState = AcxStreamStateStop;
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CStreamEngine::Pause()
+{
+ PAGED_CODE();
+
+ m_CurrentState = AcxStreamStatePause;
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CStreamEngine::Run()
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (m_CurrentState != AcxStreamStatePause)
+ {
+ status = STATUS_INVALID_STATE_TRANSITION;
+ return status;
+ }
+
+ m_CurrentState = AcxStreamStateRun;
+
+ return status;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CStreamEngine::AssignDrmContentId(
+ _In_ ULONG DrmContentId,
+ _In_ PACXDRMRIGHTS DrmRights
+)
+{
+ PAGED_CODE();
+
+ UNREFERENCED_PARAMETER(DrmContentId);
+ UNREFERENCED_PARAMETER(DrmRights);
+
+ //
+ // At this point the driver should enforce the new DrmRights.
+ //
+ // HDMI render: if DigitalOutputDisable or CopyProtect is true, enable HDCP.
+ //
+ // From MSDN:
+ //
+ // This sample doesn't forward protected content, but if your driver uses
+ // lower layer drivers or a different stack to properly work, please see the
+ // following info from MSDN:
+ //
+ // "Before allowing protected content to flow through a data path, the system
+ // verifies that the data path is secure. To do so, the system authenticates
+ // each module in the data path beginning at the upstream end of the data path
+ // and moving downstream. As each module is authenticated, that module gives
+ // the system information about the next module in the data path so that it
+ // can also be authenticated. To be successfully authenticated, a module's
+ // binary file must be signed as DRM-compliant.
+ //
+ // Two adjacent modules in the data path can communicate with each other in
+ // one of several ways. If the upstream module calls the downstream module
+ // through IoCallDriver, the downstream module is part of a WDM driver. In
+ // this case, the upstream module calls the AcxDrmForwardContentToDeviceObject
+ // function to provide the system with the device object representing the
+ // downstream module. (If the two modules communicate through the downstream
+ // module's content handlers, the upstream module calls AcxDrmAddContentHandlers
+ // instead.)
+ //
+ // For more information, see MSDN's DRM Functions and Interfaces.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CStreamEngine::GetHWLatency(
+ _Out_ ULONG * FifoSize,
+ _Out_ ULONG * Delay
+)
+{
+ PAGED_CODE();
+
+ *FifoSize = 128;
+ *Delay = 0;
+
+ return STATUS_SUCCESS;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+CRenderStreamEngine::CRenderStreamEngine(
+ _In_ ACXSTREAM Stream,
+ _In_ ACXDATAFORMAT StreamFormat
+)
+ : CStreamEngine(Stream, StreamFormat)
+{
+ PAGED_CODE();
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+CRenderStreamEngine::~CRenderStreamEngine()
+{
+ PAGED_CODE();
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CRenderStreamEngine::PrepareHardware()
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ status = CStreamEngine::PrepareHardware();
+
+ // Add other init here.
+
+ return status;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CRenderStreamEngine::ReleaseHardware()
+{
+ PAGED_CODE();
+
+ return CStreamEngine::ReleaseHardware();
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+CCaptureStreamEngine::CCaptureStreamEngine(
+ _In_ ACXSTREAM Stream,
+ _In_ ACXDATAFORMAT StreamFormat
+)
+ : CStreamEngine(Stream, StreamFormat)
+{
+ PAGED_CODE();
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+CCaptureStreamEngine::~CCaptureStreamEngine()
+{
+ PAGED_CODE();
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CCaptureStreamEngine::PrepareHardware()
+{
+ PAGED_CODE();
+
+ NTSTATUS status = STATUS_SUCCESS;
+
+ RETURN_NTSTATUS_IF_FAILED(CStreamEngine::PrepareHardware());
+
+ RETURN_NTSTATUS_IF_FAILED(ReadRegistrySettings());
+
+ return status;
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CCaptureStreamEngine::ReleaseHardware()
+{
+ PAGED_CODE();
+
+ return CStreamEngine::ReleaseHardware();
+}
+
+_Use_decl_annotations_
+PAGED_CODE_SEG
+NTSTATUS
+CCaptureStreamEngine::ReadRegistrySettings()
+{
+ PAGED_CODE();
+
+ return STATUS_SUCCESS;
+}
diff --git a/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h
new file mode 100644
index 00000000..906e21f3
--- /dev/null
+++ b/audio/SoundWire/Samples/SdcaVad/SdcaVCodec/streamengine.h
@@ -0,0 +1,131 @@
+#pragma once
+
+#define HNSTIME_PER_MILLISECOND 10000
+
+class CStreamEngine
+{
+public:
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ PrepareHardware();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ ReleaseHardware();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ Run();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ Pause();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ AssignDrmContentId(
+ _In_ ULONG DrmContentId,
+ _In_ PACXDRMRIGHTS DrmRights
+ );
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ GetHWLatency(
+ _Out_ ULONG * FifoSize,
+ _Out_ ULONG * Delay
+ );
+
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ CStreamEngine(
+ _In_ ACXSTREAM Stream,
+ _In_ ACXDATAFORMAT StreamFormat
+ );
+
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ virtual
+ #pragma code_seg()
+ ~CStreamEngine();
+
+protected:
+ ACX_STREAM_STATE m_CurrentState;
+ ACXSTREAM m_Stream;
+ ACXDATAFORMAT m_StreamFormat;
+ LARGE_INTEGER m_PerformanceCounterFrequency;
+};
+
+class CRenderStreamEngine : public CStreamEngine
+{
+public:
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ CRenderStreamEngine(
+ _In_ ACXSTREAM Stream,
+ _In_ ACXDATAFORMAT StreamFormat
+ );
+
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ ~CRenderStreamEngine();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ PrepareHardware();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ ReleaseHardware();
+
+protected:
+ // data section.
+};
+
+class CCaptureStreamEngine : public CStreamEngine
+{
+public:
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ CCaptureStreamEngine(
+ _In_ ACXSTREAM Stream,
+ _In_ ACXDATAFORMAT StreamFormat
+ );
+
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ ~CCaptureStreamEngine();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ PrepareHardware();
+
+ virtual
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ ReleaseHardware();
+
+protected:
+ __drv_maxIRQL(PASSIVE_LEVEL)
+ PAGED_CODE_SEG
+ NTSTATUS
+ ReadRegistrySettings();
+};
+