summaryrefslogtreecommitdiff
path: root/audio/sysvad/EndpointsCommon
diff options
context:
space:
mode:
authorGirish Pattabiraman <[email protected]>2017-05-03 15:02:49 -0700
committerGirish Pattabiraman <[email protected]>2017-05-03 17:20:15 -0700
commitb9027f2b8124f5853dac4355ff4d9e85379e0e56 (patch)
tree33487ba551e9e53ba5a000afc2ad8860892ef2fa /audio/sysvad/EndpointsCommon
parent32dc5459e78107ce48412eef3653370f32274561 (diff)
Audio Modules Example
Delay APO Package Project Stream Position Bug Fix SAL
Diffstat (limited to 'audio/sysvad/EndpointsCommon')
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModule0.h297
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModule1.h312
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModule2.h296
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp644
-rw-r--r--audio/sysvad/EndpointsCommon/AudioModuleHelper.h95
-rw-r--r--audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj1
-rw-r--r--audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters62
-rw-r--r--audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp1
-rw-r--r--audio/sysvad/EndpointsCommon/minwavert.cpp427
-rw-r--r--audio/sysvad/EndpointsCommon/minwavert.h86
-rw-r--r--audio/sysvad/EndpointsCommon/minwavertstream.cpp75
-rw-r--r--audio/sysvad/EndpointsCommon/minwavertstream.h37
-rw-r--r--audio/sysvad/EndpointsCommon/sources46
-rw-r--r--audio/sysvad/EndpointsCommon/speakerhpwavtable.h127
-rw-r--r--audio/sysvad/EndpointsCommon/speakerwavtable.h126
15 files changed, 2620 insertions, 12 deletions
diff --git a/audio/sysvad/EndpointsCommon/AudioModule0.h b/audio/sysvad/EndpointsCommon/AudioModule0.h
new file mode 100644
index 00000000..c1f07557
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModule0.h
@@ -0,0 +1,297 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModule0.h
+
+Abstract:
+
+ Declaration of Audio Module 0 (system module).
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULE0_H_
+#define _SYSVAD_AUDIOMODULE0_H_
+
+#include "AudioModuleHelper.h"
+
+#define AUDIOMODULE0_MAJOR 0x1
+#define AUDIOMODULE0_MINOR 0X0
+
+static const GUID AudioModule0Id =
+{ 0xe24c8b6f, 0xede7, 0x4255, 0x8b, 0x39, 0x77, 0x97, 0x60, 0x15, 0xd5, 0x93 };
+
+enum AudioModule0_Parameter {
+ AudioModule0Parameter1 = 0,
+ AudioModule0Parameter2
+};
+
+typedef struct _AUDIOMODULE0_CUSTOM_COMMAND {
+ ULONG Verb; // get, set and support
+ AudioModule0_Parameter ParameterId;
+} AUDIOMODULE0_CUSTOM_COMMAND, *PAUDIOMODULE0_CUSTOM_COMMAND;
+
+enum AudioModule0_Notification_Type {
+ AudioModule0ParameterChanged = 0,
+};
+
+typedef struct _AUDIOMODULE0_CUSTOM_NOTIFICATION {
+ ULONG Type;
+ union {
+ struct {
+ ULONG ParameterId;
+ } ParameterChanged;
+ };
+} AUDIOMODULE0_CUSTOM_NOTIFICATION, *PAUDIOMODULE0_CUSTOM_NOTIFICATION;
+
+typedef struct _AUDIOMODULE0_NOTIFICATION {
+ KSAUDIOMODULE_NOTIFICATION Header;
+ AUDIOMODULE0_CUSTOM_NOTIFICATION CustomNotification;
+} AUDIOMODULE0_NOTIFICATION, *PAUDIOMODULE0_NOTIFICATION;
+
+typedef struct _AUDIOMODULE0_CONTEXT {
+ ULONG Parameter1;
+ BYTE Parameter2;
+ ULONG InstanceId;
+ AUDIOMODULE0_NOTIFICATION Notification;
+ PPORTCLSNOTIFICATIONS PortNotifications;
+} AUDIOMODULE0_CONTEXT, *PAUDIOMODULE0_CONTEXT;
+
+static
+ULONG AudioModule0_ValidParameter1List[] =
+{
+ 1, 2, 5
+};
+
+static
+AUDIOMODULE_PARAMETER_INFO AudioModule0_ParameterInfo[] =
+{
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE0_CONTEXT, Parameter1),
+ VT_UI4,
+ AudioModule0_ValidParameter1List,
+ SIZEOF_ARRAY(AudioModule0_ValidParameter1List)
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ 0,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE0_CONTEXT, Parameter2),
+ VT_UI1,
+ NULL,
+ 0
+ },
+};
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule0_InitClass(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+ )
+{
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(Size != 0);
+ RtlZeroMemory(Context, Size);
+
+ ctx->Notification.Header = *NotificationHeader;
+ ctx->PortNotifications = PortNotifications;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule0_InitInstance(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+ )
+{
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(TemplateContext != NULL);
+ ASSERT(Size != 0);
+
+ RtlCopyMemory(Context, TemplateContext, Size);
+
+ ctx->InstanceId = InstanceId;
+ ctx->Notification.Header.ProviderId.InstanceId = InstanceId;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+VOID
+AudioModule0_Cleanup(
+ _In_ PVOID Context
+ )
+{
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return;
+ }
+
+ SAFE_RELEASE(ctx->PortNotifications);
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule0_Handler(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL fNewValue = FALSE;
+ PVOID currentValue;
+ PVOID inBuffer = NULL;
+ ULONG inBufferCb = 0;
+
+ PAUDIOMODULE0_CONTEXT ctx = (PAUDIOMODULE0_CONTEXT)Context;
+ AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL;
+ AUDIOMODULE0_CUSTOM_COMMAND * command = NULL;
+
+ PAGED_CODE();
+
+ if (ctx == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ status = STATUS_INTERNAL_ERROR;
+ goto exit;
+ }
+
+ //
+ // Basic parameter validation (module specific).
+ //
+ if (InBuffer == NULL || InBufferCb == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (InBufferCb < sizeof(AUDIOMODULE0_CUSTOM_COMMAND))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ command = (AUDIOMODULE0_CUSTOM_COMMAND*)InBuffer;
+
+ //
+ // Validate the parameter referenced in the command.
+ //
+ switch (command->ParameterId)
+ {
+ case AudioModule0Parameter1:
+ currentValue = &ctx->Parameter1;
+ parameterInfo = &AudioModule0_ParameterInfo[AudioModule0Parameter1];
+ break;
+
+ case AudioModule0Parameter2:
+ currentValue = &ctx->Parameter2;
+ parameterInfo = &AudioModule0_ParameterInfo[AudioModule0Parameter2];
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Update input buffer ptr/size.
+ //
+ inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE0_CUSTOM_COMMAND));
+ inBufferCb = InBufferCb - sizeof(AUDIOMODULE0_CUSTOM_COMMAND);
+
+ if (inBufferCb == 0)
+ {
+ inBuffer = NULL;
+ }
+
+ status = AudioModule_GenericHandler(
+ command->Verb,
+ command->ParameterId,
+ parameterInfo,
+ currentValue,
+ inBuffer,
+ inBufferCb,
+ OutBuffer,
+ OutBufferCb,
+ &fNewValue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ if (fNewValue && ctx->PortNotifications &&
+ (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION))
+ {
+ // This logic assumes that access to this function is serialized.
+ ctx->Notification.CustomNotification.Type = AudioModule0ParameterChanged;
+ ctx->Notification.CustomNotification.ParameterChanged.ParameterId =
+ command->ParameterId;
+
+ AudioModule_SendNotification(ctx->PortNotifications,
+ (PVOID)&ctx->Notification,
+ (USHORT)sizeof(ctx->Notification));
+ }
+
+ // Normalize error code.
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+#endif // _SYSVAD_AUDIOMODULE0_H_
+
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModule1.h b/audio/sysvad/EndpointsCommon/AudioModule1.h
new file mode 100644
index 00000000..9f01eaed
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModule1.h
@@ -0,0 +1,312 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModule1.h
+
+Abstract:
+
+ Declaration of Audio Module 1.
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULE1_H_
+#define _SYSVAD_AUDIOMODULE1_H_
+
+#include "AudioModuleHelper.h"
+
+#define AUDIOMODULE1_MAJOR 0x2
+#define AUDIOMODULE1_MINOR 0X1
+
+static const GUID AudioModule1Id =
+{ 0x5ce55c8e, 0x84df, 0x4317, 0x98, 0xc7, 0x79, 0x2d, 0xe8, 0x33, 0x66, 0xcc };
+
+enum AudioModule1_Parameter {
+ AudioModule1Parameter1 = 0,
+ AudioModule1Parameter2,
+ AudioModule1Parameter3
+};
+
+typedef struct _AUDIOMODULE1_CUSTOM_COMMAND {
+ ULONG Verb; // get, set and support
+ AudioModule1_Parameter ParameterId;
+} AUDIOMODULE1_CUSTOM_COMMAND, *PAUDIOMODULE1_CUSTOM_COMMAND;
+
+enum AudioModule1_Notification_Type {
+ AudioModule1ParameterChanged = 0,
+};
+
+typedef struct _AUDIOMODULE1_CUSTOM_NOTIFICATION {
+ ULONG Type;
+ union {
+ struct {
+ ULONG ParameterId;
+ } ParameterChanged;
+ };
+} AUDIOMODULE1_CUSTOM_NOTIFICATION, *PAUDIOMODULE1_CUSTOM_NOTIFICATION;
+
+typedef struct _AUDIOMODULE1_NOTIFICATION {
+ KSAUDIOMODULE_NOTIFICATION Header;
+ AUDIOMODULE1_CUSTOM_NOTIFICATION CustomNotification;
+} AUDIOMODULE1_NOTIFICATION, *PAUDIOMODULE1_NOTIFICATION;
+
+typedef struct _AUDIOMODULE1_CONTEXT {
+ BYTE Parameter1;
+ ULONGLONG Parameter2;
+ DWORD Parameter3;
+ ULONG InstanceId;
+ AUDIOMODULE1_NOTIFICATION Notification;
+ PPORTCLSNOTIFICATIONS PortNotifications;
+} AUDIOMODULE1_CONTEXT, *PAUDIOMODULE1_CONTEXT;
+
+static
+BYTE AudioModule1_ValidParameter1List[] =
+{
+ 0, 1, 2
+};
+
+static
+AUDIOMODULE_PARAMETER_INFO AudioModule1_ParameterInfo[] =
+{
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter1),
+ VT_UI1,
+ AudioModule1_ValidParameter1List,
+ SIZEOF_ARRAY(AudioModule1_ValidParameter1List)
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ 0,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter2),
+ VT_UI8,
+ NULL,
+ 0
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE1_CONTEXT, Parameter3),
+ VT_UI4,
+ NULL,
+ 0
+ },
+};
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule1_InitClass(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+ )
+{
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(Size != 0);
+ RtlZeroMemory(Context, Size);
+
+ ctx->Notification.Header = *NotificationHeader;
+ ctx->PortNotifications = PortNotifications;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule1_InitInstance(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+ )
+{
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(TemplateContext != NULL);
+ ASSERT(Size != 0);
+
+ RtlCopyMemory(Context, TemplateContext, Size);
+
+ ctx->InstanceId = InstanceId;
+ ctx->Notification.Header.ProviderId.InstanceId = InstanceId;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+VOID
+AudioModule1_Cleanup(
+ _In_ PVOID Context
+ )
+{
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return;
+ }
+
+ SAFE_RELEASE(ctx->PortNotifications);
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule1_Handler(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL fNewValue = FALSE;
+ PVOID currentValue;
+ PVOID inBuffer = NULL;
+ ULONG inBufferCb = 0;
+
+ PAUDIOMODULE1_CONTEXT ctx = (PAUDIOMODULE1_CONTEXT)Context;
+ AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL;
+ AUDIOMODULE1_CUSTOM_COMMAND * command = NULL;
+
+ PAGED_CODE();
+
+ if (ctx == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ status = STATUS_INTERNAL_ERROR;
+ goto exit;
+ }
+
+ //
+ // Basic parameter validation (module specific).
+ //
+ if (InBuffer == NULL || InBufferCb == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (InBufferCb < sizeof(AUDIOMODULE1_CUSTOM_COMMAND))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ command = (AUDIOMODULE1_CUSTOM_COMMAND*)InBuffer;
+
+ //
+ // Validate the parameter referenced in the command.
+ //
+ switch (command->ParameterId)
+ {
+ case AudioModule1Parameter1:
+ currentValue = &ctx->Parameter1;
+ parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter1];
+ break;
+
+ case AudioModule1Parameter2:
+ currentValue = &ctx->Parameter2;
+ parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter2];
+ break;
+
+ case AudioModule1Parameter3:
+ currentValue = &ctx->Parameter3;
+ parameterInfo = &AudioModule1_ParameterInfo[AudioModule1Parameter3];
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Update input buffer ptr/size.
+ //
+ inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE1_CUSTOM_COMMAND));
+ inBufferCb = InBufferCb - sizeof(AUDIOMODULE1_CUSTOM_COMMAND);
+
+ if (inBufferCb == 0)
+ {
+ inBuffer = NULL;
+ }
+
+ status = AudioModule_GenericHandler(
+ command->Verb,
+ command->ParameterId,
+ parameterInfo,
+ currentValue,
+ inBuffer,
+ inBufferCb,
+ OutBuffer,
+ OutBufferCb,
+ &fNewValue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ if (fNewValue && ctx->PortNotifications &&
+ (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION))
+ {
+ // This logic assumes that access to this function is serialized.
+ ctx->Notification.CustomNotification.Type = AudioModule1ParameterChanged;
+ ctx->Notification.CustomNotification.ParameterChanged.ParameterId =
+ command->ParameterId;
+
+ AudioModule_SendNotification(ctx->PortNotifications,
+ (PVOID)&ctx->Notification,
+ (USHORT)sizeof(ctx->Notification));
+ }
+
+ // Normalize error code.
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+#endif // _SYSVAD_AUDIOMODULE1_H_
+
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModule2.h b/audio/sysvad/EndpointsCommon/AudioModule2.h
new file mode 100644
index 00000000..93d3fdf3
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModule2.h
@@ -0,0 +1,296 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModule2.h
+
+Abstract:
+
+ Declaration of Audio Module 2.
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULE2_H_
+#define _SYSVAD_AUDIOMODULE2_H_
+
+#include "AudioModuleHelper.h"
+
+#define AUDIOMODULE2_MAJOR 0x2
+#define AUDIOMODULE2_MINOR 0X0
+
+static const GUID AudioModule2Id =
+{ 0xcc2a9527, 0x19d9, 0x4784, 0x8d, 0xd4, 0x6c, 0x1f, 0xe0, 0x1e, 0x37, 0x26 };
+
+enum AudioModule2_Parameter {
+ AudioModule2Parameter1 = 0,
+ AudioModule2Parameter2
+};
+
+typedef struct _AUDIOMODULE2_CUSTOM_COMMAND {
+ ULONG Verb; // get, set and support
+ AudioModule2_Parameter ParameterId;
+} AUDIOMODULE2_CUSTOM_COMMAND, *PAUDIOMODULE2_CUSTOM_COMMAND;
+
+enum AudioModule2_Notification_Type {
+ AudioModule2ParameterChanged = 0,
+};
+
+typedef struct _AUDIOMODULE2_CUSTOM_NOTIFICATION {
+ ULONG Type;
+ union {
+ struct {
+ ULONG ParameterId;
+ } ParameterChanged;
+ };
+} AUDIOMODULE2_CUSTOM_NOTIFICATION, *PAUDIOMODULE2_CUSTOM_NOTIFICATION;
+
+typedef struct _AUDIOMODULE2_NOTIFICATION {
+ KSAUDIOMODULE_NOTIFICATION Header;
+ AUDIOMODULE2_CUSTOM_NOTIFICATION CustomNotification;
+} AUDIOMODULE2_NOTIFICATION, *PAUDIOMODULE2_NOTIFICATION;
+
+typedef struct _AUDIOMODULE2_CONTEXT {
+ ULONG Parameter1;
+ USHORT Parameter2;
+ ULONG InstanceId;
+ AUDIOMODULE2_NOTIFICATION Notification;
+ PPORTCLSNOTIFICATIONS PortNotifications;
+} AUDIOMODULE2_CONTEXT, *PAUDIOMODULE2_CONTEXT;
+
+static
+ULONG AudioModule2_ValidParameter1List[] =
+{
+ 1, 0xfffffffe
+};
+
+static
+AUDIOMODULE_PARAMETER_INFO AudioModule2_ParameterInfo[] =
+{
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE2_CONTEXT, Parameter1),
+ VT_UI4,
+ AudioModule2_ValidParameter1List,
+ SIZEOF_ARRAY(AudioModule2_ValidParameter1List)
+ },
+ {
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ 0,
+ (ULONG)RTL_FIELD_SIZE(AUDIOMODULE2_CONTEXT, Parameter2),
+ VT_UI2,
+ NULL,
+ 0
+ },
+};
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule2_InitClass(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ KSAUDIOMODULE_NOTIFICATION * NotificationHeader,
+ _In_opt_ PPORTCLSNOTIFICATIONS PortNotifications
+ )
+{
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(Size != 0);
+ RtlZeroMemory(Context, Size);
+
+ ctx->Notification.Header = *NotificationHeader;
+ ctx->PortNotifications = PortNotifications;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule2_InitInstance(
+ _In_ const AUDIOMODULE_DESCRIPTOR * Module,
+ _In_opt_ PVOID TemplateContext,
+ _Inout_opt_ PVOID Context,
+ _In_ size_t Size,
+ _In_ ULONG InstanceId
+ )
+{
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+
+ UNREFERENCED_PARAMETER(Module);
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ ASSERT(TemplateContext != NULL);
+ ASSERT(Size != 0);
+
+ RtlCopyMemory(Context, TemplateContext, Size);
+
+ ctx->InstanceId = InstanceId;
+ ctx->Notification.Header.ProviderId.InstanceId = InstanceId;
+ if (ctx->PortNotifications != NULL)
+ {
+ ctx->PortNotifications->AddRef();
+ }
+
+ return STATUS_SUCCESS;
+}
+
+inline
+#pragma code_seg("PAGE")
+VOID
+AudioModule2_Cleanup(
+ _In_ PVOID Context
+ )
+{
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+
+ PAGED_CODE();
+
+ if (Context == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ return;
+ }
+
+ SAFE_RELEASE(ctx->PortNotifications);
+}
+
+inline
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule2_Handler(
+ _Inout_opt_ PVOID Context,
+ _In_reads_bytes_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ BOOL fNewValue = FALSE;
+ PVOID currentValue;
+ PVOID inBuffer = NULL;
+ ULONG inBufferCb = 0;
+
+ PAUDIOMODULE2_CONTEXT ctx = (PAUDIOMODULE2_CONTEXT)Context;
+ AUDIOMODULE_PARAMETER_INFO * parameterInfo = NULL;
+ AUDIOMODULE2_CUSTOM_COMMAND * command = NULL;
+
+ PAGED_CODE();
+
+ if (ctx == NULL)
+ {
+ ASSERT(FALSE); // this should not happen.
+ status = STATUS_INTERNAL_ERROR;
+ goto exit;
+ }
+
+ //
+ // Basic parameter validation (module specific).
+ //
+ if (InBuffer == NULL || InBufferCb == 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (InBufferCb < sizeof(AUDIOMODULE2_CUSTOM_COMMAND))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ command = (AUDIOMODULE2_CUSTOM_COMMAND*)InBuffer;
+
+ //
+ // Validate the parameter referenced in the command.
+ //
+ switch (command->ParameterId)
+ {
+ case AudioModule2Parameter1:
+ currentValue = &ctx->Parameter1;
+ parameterInfo = &AudioModule2_ParameterInfo[AudioModule0Parameter1];
+ break;
+
+ case AudioModule2Parameter2:
+ currentValue = &ctx->Parameter2;
+ parameterInfo = &AudioModule2_ParameterInfo[AudioModule2Parameter2];
+ break;
+
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Update input buffer ptr/size.
+ //
+ inBuffer = (PVOID)((ULONG_PTR)InBuffer + sizeof(AUDIOMODULE2_CUSTOM_COMMAND));
+ inBufferCb = InBufferCb - sizeof(AUDIOMODULE2_CUSTOM_COMMAND);
+
+ if (inBufferCb == 0)
+ {
+ inBuffer = NULL;
+ }
+
+ status = AudioModule_GenericHandler(
+ command->Verb,
+ command->ParameterId,
+ parameterInfo,
+ currentValue,
+ inBuffer,
+ inBufferCb,
+ OutBuffer,
+ OutBufferCb,
+ &fNewValue);
+
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ if (fNewValue && ctx->PortNotifications &&
+ (parameterInfo->Flags & AUDIOMODULE_PARAMETER_FLAG_CHANGE_NOTIFICATION))
+ {
+ // This logic assumes that access to this function is serialized.
+ ctx->Notification.CustomNotification.Type = AudioModule2ParameterChanged;
+ ctx->Notification.CustomNotification.ParameterChanged.ParameterId =
+ command->ParameterId;
+
+ AudioModule_SendNotification(ctx->PortNotifications,
+ (PVOID)&ctx->Notification,
+ (USHORT)sizeof(ctx->Notification));
+ }
+
+ // Normalize error code.
+ status = STATUS_SUCCESS;
+
+exit:
+ return status;
+}
+
+#endif // _SYSVAD_AUDIOMODULE2_H_
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp b/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp
new file mode 100644
index 00000000..f93c2bff
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp
@@ -0,0 +1,644 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModuleHelper.cpp
+
+Abstract:
+
+ Simple helper for Audio Modules logic.
+
+--*/
+
+#pragma warning (disable : 4127)
+
+#include <sysvad.h>
+#include <limits.h>
+#include <ntintsafe.h>
+#include "SysVadShared.h"
+#include "AudioModuleHelper.h"
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_BasicSupport(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer,
+ _Inout_ ULONG * BufferCb
+ )
+{
+ NTSTATUS ntStatus = STATUS_SUCCESS;
+ ULONG cbFullProperty = 0;
+ ULONG cbDataListSize = 0;
+
+ DPF_ENTER(("[AudioModule_GenericHandler_BasicSupport]"));
+
+ PAGED_CODE();
+
+ ASSERT(ParameterInfo);
+ ASSERT(BufferCb);
+
+ //
+ // Compute total size of property.
+ //
+ ntStatus = RtlULongMult(ParameterInfo->Size,
+ ParameterInfo->ValidSetCount,
+ &cbDataListSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ *BufferCb = 0;
+ return ntStatus;
+ }
+
+ ntStatus = RtlULongAdd(cbDataListSize,
+ (ULONG)(sizeof(KSPROPERTY_DESCRIPTION) +
+ sizeof(KSPROPERTY_MEMBERSHEADER)),
+ &cbFullProperty);
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ *BufferCb = 0;
+ return ntStatus;
+ }
+
+ //
+ // Return the info the caller is asking for.
+ //
+ if (*BufferCb == 0)
+ {
+ // caller wants to know the size of the buffer.
+ *BufferCb = cbFullProperty;
+ ntStatus = STATUS_BUFFER_OVERFLOW;
+ }
+ else if (*BufferCb >= (sizeof(KSPROPERTY_DESCRIPTION)))
+ {
+ PKSPROPERTY_DESCRIPTION propDesc = PKSPROPERTY_DESCRIPTION(Buffer);
+
+ propDesc->AccessFlags = ParameterInfo->AccessFlags;
+ propDesc->DescriptionSize = cbFullProperty;
+ propDesc->PropTypeSet.Set = KSPROPTYPESETID_General;
+ propDesc->PropTypeSet.Id = ParameterInfo->VtType;
+ propDesc->PropTypeSet.Flags = 0;
+ propDesc->MembersListCount = 1;
+ propDesc->Reserved = 0;
+
+ // if return buffer can also hold a list description, return it too
+ if(*BufferCb >= cbFullProperty)
+ {
+ // fill in the members header
+ PKSPROPERTY_MEMBERSHEADER members =
+ PKSPROPERTY_MEMBERSHEADER(propDesc + 1);
+
+ members->MembersFlags = KSPROPERTY_MEMBER_VALUES;
+ members->MembersSize = ParameterInfo->Size;
+ members->MembersCount = ParameterInfo->ValidSetCount;
+ members->Flags = KSPROPERTY_MEMBER_FLAG_DEFAULT;
+
+ // fill in valid array.
+ BYTE* array = (BYTE*)(members + 1);
+
+ RtlCopyMemory(array, ParameterInfo->ValidSet, cbDataListSize);
+
+ // set the return value size
+ *BufferCb = cbFullProperty;
+ }
+ else
+ {
+ *BufferCb = sizeof(KSPROPERTY_DESCRIPTION);
+ }
+ }
+ else if(*BufferCb >= sizeof(ULONG))
+ {
+ // if return buffer can hold a ULONG, return the access flags
+ PULONG accessFlags = PULONG(Buffer);
+
+ *BufferCb = sizeof(ULONG);
+ *accessFlags = ParameterInfo->AccessFlags;
+ }
+ else
+ {
+ *BufferCb = 0;
+ ntStatus = STATUS_BUFFER_TOO_SMALL;
+ }
+
+ return ntStatus;
+} // PropertyHandlerBasicSupportVolume
+
+//=============================================================================
+#pragma code_seg("PAGE")
+BOOLEAN
+IsAudioModuleParameterValid(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _In_reads_bytes_opt_(BufferCb) PVOID Buffer,
+ _In_ ULONG BufferCb
+ )
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[IsAudioModuleParameterValid]"));
+
+ ULONG i = 0;
+ ULONG j = 0;
+ BOOLEAN validParam = FALSE;
+
+ //
+ // Validate buffer ptr and size.
+ //
+ if (Buffer == NULL || BufferCb == 0)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+
+ //
+ // Check its size.
+ //
+ if (BufferCb < ParameterInfo->Size)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+
+ //
+ // Check the valid list.
+ //
+ if (ParameterInfo->ValidSet && ParameterInfo->ValidSetCount)
+ {
+ BYTE* buffer = (BYTE*)ParameterInfo->ValidSet;
+ BYTE* pattern = (BYTE*)Buffer;
+
+ //
+ // Scan the valid list.
+ //
+ for (i = 0; i < ParameterInfo->ValidSetCount; ++i)
+ {
+ for (j=0; j < ParameterInfo->Size; ++j)
+ {
+ if (buffer[j] != pattern[j])
+ {
+ break;
+ }
+ }
+
+ if (j == ParameterInfo->Size)
+ {
+ // got a match.
+ break;
+ }
+
+ buffer += ParameterInfo->Size;
+ }
+
+ //
+ // If end of list, we didn't find the value.
+ //
+ if (i == ParameterInfo->ValidSetCount)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+ }
+ else
+ {
+ //
+ // Negative-testing support. Fail request if value is -1.
+ //
+ BYTE* buffer = (BYTE*)Buffer;
+
+ for (i = 0; i < ParameterInfo->Size; ++i)
+ {
+ if (buffer[i] != 0xFF)
+ {
+ break;
+ }
+ }
+
+ //
+ // If value is -1, return error.
+ //
+ if (i == ParameterInfo->Size)
+ {
+ validParam = FALSE;
+ goto exit;
+ }
+ }
+
+ validParam = TRUE;
+
+exit:
+ return validParam;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+AUDIOMODULE *
+AudioModule_FindModuleInList(
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount,
+ _In_ GUID * ClassId,
+ _In_ ULONG InstanceId
+ )
+{
+ for (ULONG i=0; i<AudioModuleCount; ++i)
+ {
+ AUDIOMODULE * module = &AudioModules[i];
+
+ if (IsEqualGUIDAligned(*(module->Descriptor->ClassId), *ClassId) &&
+ module->InstanceId == InstanceId)
+ {
+ return module;
+ }
+ }
+
+ return NULL;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler(
+ _In_ ULONG Verb,
+ _In_ ULONG ParameterId,
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue,
+ _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb,
+ _In_ BOOL * ParameterChanged
+ )
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_GenericHandler]"));
+
+ UNREFERENCED_PARAMETER(ParameterId);
+
+ *ParameterChanged = FALSE;
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ return AudioModule_GenericHandler_BasicSupport(ParameterInfo, OutBuffer, OutBufferCb);
+ }
+
+ ULONG cbMinSize = ParameterInfo->Size;
+
+ if (Verb & KSPROPERTY_TYPE_GET)
+ {
+ // Verify module parameter supports 'get'.
+ if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_GET))
+ {
+ *OutBufferCb = 0;
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Verify value size
+ if (*OutBufferCb == 0)
+ {
+ *OutBufferCb = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (*OutBufferCb < cbMinSize)
+ {
+ *OutBufferCb = 0;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ RtlCopyMemory(OutBuffer, CurrentValue, ParameterInfo->Size);
+ *OutBufferCb = cbMinSize;
+ return STATUS_SUCCESS;
+ }
+ }
+ else if (Verb & KSPROPERTY_TYPE_SET)
+ {
+ *OutBufferCb = 0;
+
+ // Verify it is a write prop.
+ if (!(ParameterInfo->AccessFlags & KSPROPERTY_TYPE_SET))
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Validate parameter.
+ if (!IsAudioModuleParameterValid(ParameterInfo, InBuffer, InBufferCb))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (ParameterInfo->Size !=
+ RtlCompareMemory(CurrentValue, InBuffer, ParameterInfo->Size))
+ {
+ RtlCopyMemory(CurrentValue, InBuffer, ParameterInfo->Size);
+ *ParameterChanged = TRUE;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModulesListRequest(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ )
+{
+ NTSTATUS ntStatus;
+
+ // This specific APO->driver communication example is mainly added to show how this communication is done.
+ // The module list only lives on the wave filter and it can have modules that are for all pins and some that
+ // are only on specific pins.
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_PropertyHandlerModulesListRequest]"));
+
+ //
+ // Note: return an empty list when no modules are present.
+ //
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ PKSMULTIPLE_ITEM ksMultipleItem;
+ ULONG cbMinSize = 0;
+ PKSAUDIOMODULE_DESCRIPTOR modules = NULL;
+
+ //
+ // Compute min value size requirements
+ //
+ ntStatus = RtlULongMult(AudioModuleCount,
+ (ULONG)sizeof(KSAUDIOMODULE_DESCRIPTOR),
+ &cbMinSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ return ntStatus;
+ }
+
+ ntStatus = RtlULongAdd(cbMinSize, sizeof(KSMULTIPLE_ITEM), &cbMinSize);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ return ntStatus;
+ }
+
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ // Value is a KSMULTIPLE_ITEM followed by list of modules.
+ ksMultipleItem = (PKSMULTIPLE_ITEM)PropertyRequest->Value;
+ modules = (PKSAUDIOMODULE_DESCRIPTOR)(ksMultipleItem + 1);
+
+ // Copy modules
+ for (ULONG i = 0; i<AudioModuleCount; ++i, ++modules)
+ {
+ const AUDIOMODULE_DESCRIPTOR * moduleDesc = AudioModules[i].Descriptor;
+
+ modules->ClassId = *moduleDesc->ClassId;
+ modules->InstanceId = AudioModules[i].InstanceId;
+
+ modules->VersionMajor = moduleDesc->VersionMajor;
+ modules->VersionMinor = moduleDesc->VersionMinor;
+
+
+ RtlStringCchCopyW(modules->Name,
+ AUDIOMODULE_MAX_NAME_CCH_SIZE, // includes null char
+ moduleDesc->Name);
+ }
+
+ // Miniport filled in the list of modules. Fill in the KSMULTIPLE_ITEM header.
+ ksMultipleItem->Size = cbMinSize;
+ ksMultipleItem->Count = AudioModuleCount;
+
+ PropertyRequest->ValueSize = ksMultipleItem->Size;
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+} // AudioModule_GenericHandler_ModulesListRequest
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleCommand(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ )
+{
+ AUDIOMODULE * module = NULL;
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_GenericHandler_ModuleCommand]"));
+
+ //
+ // Basic parameter validation.
+ //
+ if (AudioModules == NULL || AudioModuleCount == 0)
+ {
+ // endpoint/stream doesn't have any modules.
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Verify instance data stores at least KSAUDIOMODULE_PROPERTY fields
+ // beyond KSPPROPERTY.
+ if (PropertyRequest->InstanceSize < (sizeof(KSAUDIOMODULE_PROPERTY) -
+ RTL_SIZEOF_THROUGH_FIELD(KSAUDIOMODULE_PROPERTY, Property)))
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Extract property descriptor from property request instance data
+ PKSAUDIOMODULE_PROPERTY moduleProperty = CONTAINING_RECORD(
+ PropertyRequest->Instance, KSAUDIOMODULE_PROPERTY, ClassId);
+
+ // Get a ptr to the module.
+ module = AudioModule_FindModuleInList(AudioModules,
+ AudioModuleCount,
+ &moduleProperty->ClassId,
+ moduleProperty->InstanceId);
+ //
+ // Invoke the handler.
+ //
+ if (module == NULL ||
+ module->Descriptor == NULL ||
+ module->Descriptor->Handler == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ // Only KS-get is supported.
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ NTSTATUS status;
+ ULONG inBufferCb = 0;
+ ULONG outBufferCb = 0;
+ PVOID inBuffer = NULL;
+ PVOID outBuffer = NULL;
+
+ outBufferCb = PropertyRequest->ValueSize;
+ outBuffer = PropertyRequest->Value;
+
+ ASSERT((outBufferCb != 0 && outBuffer != NULL) ||
+ (outBufferCb == 0 && outBuffer == NULL));
+
+ // this is guaranteed to work b/c of the validation above.
+ inBufferCb = PropertyRequest->InstanceSize +
+ sizeof(KSPROPERTY) -
+ sizeof(KSAUDIOMODULE_PROPERTY);
+
+ if (inBufferCb != 0)
+ {
+ inBuffer = (PVOID)(moduleProperty+1);
+ }
+
+ status = module->Descriptor->Handler(module->Context,
+ inBuffer,
+ inBufferCb,
+ outBuffer,
+ &outBufferCb);
+ //
+ // Set the size of the returned output data, or in the case of
+ // buffer overflow error, return the expected buffer length.
+ //
+ PropertyRequest->ValueSize = outBufferCb;
+ return status;
+ }
+
+ PropertyRequest->ValueSize = 0;
+ return STATUS_INVALID_DEVICE_REQUEST;
+} // AudioModule_GenericHandler_ModuleCommand
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleNotificationDeviceId(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ const GUID * NotificationDeviceId
+ )
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_GenericHandler_ModuleNotificationDeviceId]"));
+
+ //
+ // Basic parameter validation.
+ //
+ if (NotificationDeviceId == NULL)
+ {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ // Handle KSPROPERTY_TYPE_BASICSUPPORT query
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
+ {
+ ULONG flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT;
+
+ return PropertyHandler_BasicSupport(PropertyRequest, flags, VT_ILLEGAL);
+ }
+
+ ULONG cbMinSize = sizeof(GUID);
+ GUID *dataPtr = static_cast<GUID*>(PropertyRequest->Value);
+
+ if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
+ {
+ // Verify value size
+ if (PropertyRequest->ValueSize == 0)
+ {
+ PropertyRequest->ValueSize = cbMinSize;
+ return STATUS_BUFFER_OVERFLOW;
+ }
+ if (PropertyRequest->ValueSize < cbMinSize)
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ *dataPtr = *NotificationDeviceId;
+ PropertyRequest->ValueSize = cbMinSize;
+
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
+VOID
+AudioModule_SendNotification(
+ _In_ PPORTCLSNOTIFICATIONS PortNotifications,
+ _In_ PVOID NotificationBuffer,
+ _In_ USHORT NotificationBufferCb
+ )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PPCNOTIFICATION_BUFFER buffer = NULL;
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[AudioModule_SendNotification]"));
+
+ // Allocate a notification buffer.
+ status = PortNotifications->AllocNotificationBuffer(PagedPool,
+ NotificationBufferCb,
+ &buffer);
+ if (!NT_SUCCESS(status))
+ {
+ goto exit;
+ }
+
+ // Notification buffer is only guaranteed to be LONG aligned,
+ // it is received as ULONGLONG aligned on the receiving end.
+ RtlCopyMemory(buffer, NotificationBuffer, NotificationBufferCb);
+
+ //
+ // Generate notification (async).
+ //
+ PortNotifications->SendNotification(&KSNOTIFICATIONID_AudioModule, buffer);
+
+exit:
+ if (buffer != NULL)
+ {
+ // Free notification buffer.
+ PortNotifications->FreeNotificationBuffer(buffer);
+ buffer = NULL;
+ }
+}
+
+
diff --git a/audio/sysvad/EndpointsCommon/AudioModuleHelper.h b/audio/sysvad/EndpointsCommon/AudioModuleHelper.h
new file mode 100644
index 00000000..fa7a2c23
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/AudioModuleHelper.h
@@ -0,0 +1,95 @@
+/*++
+
+Copyright (c) Microsoft Corporation All Rights Reserved
+
+Module Name:
+
+ AudioModuleHelper.h
+
+Abstract:
+
+ Simple helper for Audio Modules logic.
+
+--*/
+
+#ifndef _SYSVAD_AUDIOMODULEHELPER_H_
+#define _SYSVAD_AUDIOMODULEHELPER_H_
+
+//
+// Module helper functions.
+//
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_BasicSupport(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Out_writes_bytes_opt_(*BufferCb) PVOID Buffer,
+ _Inout_ ULONG * BufferCb
+ );
+
+#pragma code_seg("PAGE")
+BOOLEAN
+IsAudioModuleParameterValid(
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _In_reads_bytes_opt_(BufferCb) PVOID Buffer,
+ _In_ ULONG BufferCb
+ );
+
+#pragma code_seg("PAGE")
+AUDIOMODULE *
+AudioModule_FindModuleInList(
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount,
+ _In_ GUID * ClassId,
+ _In_ ULONG InstanceId
+ );
+
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler(
+ _In_ ULONG Verb,
+ _In_ ULONG ParameterId,
+ _In_ PAUDIOMODULE_PARAMETER_INFO ParameterInfo,
+ _Inout_updates_bytes_(ParameterInfo->Size) PVOID CurrentValue,
+ _In_reads_bytes_opt_(InBufferCb) PVOID InBuffer,
+ _In_ ULONG InBufferCb,
+ _Out_writes_bytes_opt_(*OutBufferCb) PVOID OutBuffer,
+ _Inout_ ULONG * OutBufferCb,
+ _In_ BOOL * ParameterChanged
+ );
+
+//
+// Miniport/Stream helper functions.
+//
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModulesListRequest(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ );
+
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleCommand(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ AUDIOMODULE * AudioModules,
+ _In_ ULONG AudioModuleCount
+ );
+
+#pragma code_seg("PAGE")
+NTSTATUS
+AudioModule_GenericHandler_ModuleNotificationDeviceId(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest,
+ _In_ const GUID * NotificationDeviceId
+ );
+
+#pragma code_seg("PAGE")
+VOID
+AudioModule_SendNotification(
+ _In_ PPORTCLSNOTIFICATIONS PortNotifications,
+ _In_ PVOID NotificationBuffer,
+ _In_ USHORT NotificationBufferCb
+ );
+#endif // _SYSVAD_AUDIOMODULEHELPER_H_
+
+
diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
index 1956d106..4fb3fda6 100644
--- a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
+++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj
@@ -157,6 +157,7 @@
</Midl>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="AudioModuleHelper.cpp" />
<ClCompile Include="bthhfpmictopo.cpp" />
<ClCompile Include="bthhfpminwavert.cpp" />
<ClCompile Include="bthhfpspeakertopo.cpp" />
diff --git a/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters
new file mode 100644
index 00000000..0579c299
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions>
+ <UniqueIdentifier>{CDBBEDA3-98E9-4C7A-BDB1-25EC47D0B087}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ <UniqueIdentifier>{FA3DF57E-BA19-4783-831B-CF9D4D594F70}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions>
+ <UniqueIdentifier>{CB830E4F-01DA-4D35-9789-E7DB0D02A79C}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Driver Files">
+ <Extensions>inf;inv;inx;mof;mc;</Extensions>
+ <UniqueIdentifier>{49F92783-3B39-4D0C-A153-8C346F754749}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="AudioModuleHelper.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfpmictopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfpminwavert.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfpspeakertopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="bthhfptopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="micarraytopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="MiniportAudioEngineNode.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="MiniportStreamAudioEngineNode.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="mintopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="minwavert.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="minwavertstream.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="speakerhptopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="speakertopo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp
index a210f77b..0f772155 100644
--- a/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp
+++ b/audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp
@@ -996,3 +996,4 @@ NTSTATUS CMiniportWaveRTStream::SetStreamCurrentWritePositionForLastBuffer(_In_
return ntStatus;
}
+
diff --git a/audio/sysvad/EndpointsCommon/minwavert.cpp b/audio/sysvad/EndpointsCommon/minwavert.cpp
index 53fcfac2..35923619 100644
--- a/audio/sysvad/EndpointsCommon/minwavert.cpp
+++ b/audio/sysvad/EndpointsCommon/minwavert.cpp
@@ -22,6 +22,8 @@ Abstract:
#include "minwavert.h"
#include "minwavertstream.h"
#include "IHVPrivatePropertySet.h"
+#include "AudioModuleHelper.h"
+
//=============================================================================
// CMiniportWaveRT
@@ -37,7 +39,7 @@ CreateMiniportWaveRTSYSVAD
_In_opt_ PUNKNOWN UnknownOuter,
_When_((PoolType & NonPagedPoolMustSucceed) != 0,
__drv_reportError("Must succeed pool allocations are forbidden. "
- "Allocation failures cause a system crash"))
+ "Allocation failures cause a system crash"))
_In_ POOL_TYPE PoolType,
_In_ PUNKNOWN UnknownAdapter,
_In_opt_ PVOID DeviceContext,
@@ -161,6 +163,12 @@ Return Value:
m_pPortEvents = NULL;
}
+ if (m_pPortClsNotifications)
+ {
+ m_pPortClsNotifications->Release();
+ m_pPortClsNotifications = NULL;
+ }
+
if (m_SystemStreams)
{
ExFreePoolWithTag( m_SystemStreams, MINWAVERT_POOLTAG );
@@ -178,7 +186,13 @@ Return Value:
ExFreePoolWithTag( m_LoopbackStreams, MINWAVERT_POOLTAG );
m_LoopbackStreams = NULL;
}
-
+
+ if (m_pAudioModules)
+ {
+ FreeStreamAudioModules(m_pAudioModules, GetAudioModuleListCount());
+ m_pAudioModules = NULL;
+ }
+
#ifdef SYSVAD_BTH_BYPASS
if (IsBthHfpDevice())
{
@@ -392,6 +406,80 @@ Return Value:
m_LoopbackProtection = CONSTRICTOR_OPTION_DISABLE;
RtlZeroMemory(&m_MixDrmRights, sizeof(m_MixDrmRights));
+ //
+ // For port notification support.
+ //
+ if (!NT_SUCCESS(Port_->QueryInterface(IID_IPortClsNotifications, (PVOID *)&m_pPortClsNotifications)))
+ {
+ m_pPortClsNotifications = NULL;
+ }
+
+ //
+ // Init all the modules associated to this miniport.
+ //
+ ULONG cModules = GetAudioModuleListCount();
+ if (cModules)
+ {
+ //
+ // Module list size.
+ //
+ size = cModules * sizeof(AUDIOMODULE);
+ m_pAudioModules = (AUDIOMODULE *)ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+ if (m_pAudioModules == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(m_pAudioModules, size);
+
+ for (ULONG i=0; i<cModules; ++i)
+ {
+ PAUDIOMODULE_DESCRIPTOR moduleDesc = &m_pMiniportPair->ModuleList[i];
+
+ //
+ // Init run-time module element.
+ //
+ m_pAudioModules[i].Descriptor = moduleDesc;
+ m_pAudioModules[i].Context = NULL;
+ m_pAudioModules[i].InstanceId = moduleDesc->InstanceId;
+ m_pAudioModules[i].Enabled = TRUE;
+ //
+ // Module context size.
+ //
+ size = moduleDesc->ContextSize;
+ if (size)
+ {
+ m_pAudioModules[i].Context =
+ ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+
+ if (m_pAudioModules[i].Context == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(m_pAudioModules[i].Context, size);
+ }
+
+
+ if (moduleDesc->InitClass)
+ {
+ KSAUDIOMODULE_NOTIFICATION NotificationHeader;
+ NotificationHeader.ProviderId.DeviceId = *GetAudioModuleNotificationDeviceId();
+ NotificationHeader.ProviderId.ClassId = *moduleDesc->ClassId;
+ NotificationHeader.ProviderId.InstanceId = moduleDesc->InstanceId;
+
+ ntStatus = moduleDesc->InitClass(moduleDesc,
+ m_pAudioModules[i].Context,
+ size,
+ &NotificationHeader,
+ m_pPortClsNotifications);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ return ntStatus;
+ }
+ }
+ }
+ }
+
//
// Init the audio-engine used by the render devices.
//
@@ -1294,6 +1382,63 @@ CMiniportWaveRT::PropertyHandlerProposedFormat
return ntStatus;
} // PropertyHandlerProposedFormat
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerModulesListRequest
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ // This specific APO->driver communication example is mainly added to show how this communication is done.
+ // The module list only lives on the wave filter and it can have modules that are for all pins and some that
+ // are only on specific pins.
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModulesListRequest]"));
+
+ return AudioModule_GenericHandler_ModulesListRequest(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModulesListRequest
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerModuleCommand
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModuleCommand]"));
+
+ return AudioModule_GenericHandler_ModuleCommand(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModuleCommand
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::PropertyHandlerModuleNotificationDeviceId
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRT::PropertyHandlerModuleNotificationDeviceId]"));
+
+ return AudioModule_GenericHandler_ModuleNotificationDeviceId(
+ PropertyRequest,
+ GetAudioModuleNotificationDeviceId());
+} // PropertyHandlerModuleNotificationDeviceId
+
//=============================================================================
#pragma code_seg("PAGE")
@@ -1677,6 +1822,203 @@ Return Value:
//=============================================================================
#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRT::AllocStreamAudioModules
+(
+ _In_ const GUID * SignalProcessingMode,
+ _Out_ AUDIOMODULE ** ppAudioModules,
+ _Out_ ULONG * pAudioModuleCount
+)
+{
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_STATE;
+ AUDIOMODULE * pAudioModules = NULL;
+ ULONG cModules = 0;
+ ULONG i, j;
+ size_t size;
+
+ PAGED_CODE();
+
+ //
+ // Init out parameters.
+ //
+ *ppAudioModules = NULL;
+ *pAudioModuleCount = 0;
+
+ //
+ // Nothing to do if there are no modules.
+ //
+ if (m_pAudioModules == NULL)
+ {
+ ntStatus = STATUS_SUCCESS;
+ goto exit;
+ }
+
+ //
+ // Find the # of modules associated with this stream.
+ //
+ for (i=0; i<GetAudioModuleListCount(); ++i)
+ {
+ const AUDIOMODULE_DESCRIPTOR * moduleDesc = m_pAudioModules[i].Descriptor;
+
+ if (IsEqualGUIDAligned(*moduleDesc->ProcessingMode, *SignalProcessingMode) ||
+ IsEqualGUIDAligned(*moduleDesc->ProcessingMode, NULL_GUID))
+ {
+ cModules++;
+ }
+ }
+
+ //
+ // All done if module count is zero.
+ //
+ if (cModules == 0)
+ {
+ ntStatus = STATUS_SUCCESS;
+ goto exit;
+ }
+
+ //
+ // Alloc modules infrastructure.
+ //
+ size = cModules * sizeof(AUDIOMODULE);
+#pragma prefast(suppress:__WARNING_MEMORY_LEAK,"No leaking, stream obj dtor calls FreeStreamAudioModules")
+ pAudioModules = (AUDIOMODULE *)ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+ if (pAudioModules == NULL)
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+ RtlZeroMemory(pAudioModules, size);
+
+ for (i=0, j=0; i<GetAudioModuleListCount() && j<cModules; ++i)
+ {
+ const AUDIOMODULE_DESCRIPTOR * moduleDesc = m_pAudioModules[i].Descriptor;
+
+ if (IsEqualGUIDAligned(*moduleDesc->ProcessingMode, *SignalProcessingMode) ||
+ IsEqualGUIDAligned(*moduleDesc->ProcessingMode, NULL_GUID))
+ {
+ ULONG CfgInstanceId;
+
+ //
+ // Init run-time module element.
+ //
+ pAudioModules[j].Descriptor = moduleDesc;
+ pAudioModules[j].Context = NULL;
+
+ //
+ // Create a unique InstanceId for this module instance.
+ // This sample uses 24bits index which wraps around after 16M
+ // module instances for a specific class ID/Class config id.
+ // A real driver should reuse instance ids of deleted module
+ // instances, i.e., the driver should use a mapping between
+ // index <--> module info.
+ //
+ CfgInstanceId = InterlockedIncrement((LONG*)&m_pAudioModules[i].NextCfgInstanceId);
+
+ pAudioModules[j].InstanceId =
+ AUDIOMODULE_INSTANCE_ID(AUDIOMODULE_GET_CLASSCFGID(m_pAudioModules[i].InstanceId),
+ CfgInstanceId);
+
+ pAudioModules[j].Enabled = m_pAudioModules[i].Enabled;
+
+ //
+ // Alloc context for module instance.
+ //
+ size = moduleDesc->ContextSize;
+ if (size)
+ {
+#pragma prefast(suppress:__WARNING_MEMORY_LEAK,"No leaking, stream obj dtor calls FreeStreamAudioModules")
+ pAudioModules[j].Context =
+ ExAllocatePoolWithTag(NonPagedPoolNx, size, MINWAVERT_POOLTAG);
+
+ if (pAudioModules[j].Context == NULL)
+ {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto exit;
+ }
+ RtlZeroMemory(pAudioModules[j].Context, size);
+ }
+
+ //
+ // Init this module instance.
+ //
+ if (moduleDesc->InitInstance)
+ {
+ ntStatus = moduleDesc->InitInstance(moduleDesc,
+ m_pAudioModules[i].Context,
+ pAudioModules[j].Context,
+ size,
+ pAudioModules[j].InstanceId);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ ASSERT(FALSE);
+ goto exit;
+ }
+ }
+
+ //
+ // Update stream module array index.
+ //
+ j++;
+ }
+ }
+
+ //
+ // Return the list of modules.
+ //
+ *ppAudioModules = pAudioModules;
+ *pAudioModuleCount = cModules;
+
+ ntStatus = STATUS_SUCCESS;
+
+exit:
+
+ if (!NT_SUCCESS(ntStatus))
+ {
+ if (pAudioModules != NULL)
+ {
+ FreeStreamAudioModules(pAudioModules, cModules);
+ pAudioModules = NULL;
+ cModules = 0;
+ }
+ }
+
+ return ntStatus;
+}
+
+#pragma code_seg("PAGE")
+VOID
+CMiniportWaveRT::FreeStreamAudioModules
+(
+ _In_ AUDIOMODULE * pAudioModules,
+ _In_ ULONG AudioModuleCount
+)
+{
+ PAGED_CODE();
+
+ if (pAudioModules != NULL)
+ {
+ ASSERT(AudioModuleCount);
+
+ for (ULONG i=0; i<AudioModuleCount; ++i)
+ {
+ if (pAudioModules[i].Context)
+ {
+ if (pAudioModules[i].Descriptor->Cleanup)
+ {
+ pAudioModules[i].Descriptor->Cleanup(pAudioModules[i].Context);
+ }
+
+ ExFreePoolWithTag(pAudioModules[i].Context, MINWAVERT_POOLTAG);
+ pAudioModules[i].Context = NULL;
+ }
+ }
+
+ ExFreePoolWithTag(pAudioModules, MINWAVERT_POOLTAG);
+ }
+}
+
+//=============================================================================
+#pragma code_seg("PAGE")
DEFINE_CLASSPROPERTYHANDLER(CMiniportWaveRT, Get_SoundDetectorSupportedPatterns)
{
@@ -1937,6 +2279,24 @@ Return Value:
DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]"));
}
}
+ else if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioModule))
+ {
+ switch (PropertyRequest->PropertyItem->Id)
+ {
+ case KSPROPERTY_AUDIOMODULE_DESCRIPTORS:
+ ntStatus = pWaveHelper->PropertyHandlerModulesListRequest(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_COMMAND:
+ ntStatus = pWaveHelper->PropertyHandlerModuleCommand(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID:
+ ntStatus = pWaveHelper->PropertyHandlerModuleNotificationDeviceId(PropertyRequest);
+ break;
+
+ default:
+ DPF(D_TERSE, ("[PropertyHandler_WaveFilter: Invalid Device Request]"));
+ }
+ }
else if ((pWaveHelper->m_DeviceType == eHdmiRenderDevice ||
pWaveHelper->m_DeviceType == eCellularDevice ||
pWaveHelper->m_DeviceType == eHandsetSpeakerDevice) &&
@@ -2061,6 +2421,69 @@ PropertyHandler_OffloadPin
return ntStatus;
}
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+PropertyHandler_GenericPin
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
+ CMiniportWaveRT* pWave = NULL;
+ CMiniportWaveRTStream * pStream = NULL;
+
+ PAGED_CODE();
+
+ if (PropertyRequest->MajorTarget == NULL ||
+ PropertyRequest->MinorTarget == NULL)
+ {
+ ntStatus = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ //
+ // Get a ref to the miniport.
+ //
+ pWave = MajorTarget_to_Obj(PropertyRequest->MajorTarget);
+ pWave->AddRef();
+
+ //
+ // Get a ref to the stream.
+ //
+ pStream = MinorTarget_to_Obj(PropertyRequest->MinorTarget);
+ pStream->AddRef();
+
+ //
+ // Invoke appropriate handle.
+ //
+ if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_AudioModule))
+ {
+ switch (PropertyRequest->PropertyItem->Id)
+ {
+ case KSPROPERTY_AUDIOMODULE_DESCRIPTORS:
+ ntStatus = pStream->PropertyHandlerModulesListRequest(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_COMMAND:
+ ntStatus = pStream->PropertyHandlerModuleCommand(PropertyRequest);
+ break;
+ case KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID:
+ // Filter handles this prop.
+ ntStatus = pWave->PropertyHandlerModuleNotificationDeviceId(PropertyRequest);
+ break;
+
+ default:
+ DPF(D_TERSE, ("[PropertyHandler_GenericPin: Invalid Device Request]"));
+ }
+ }
+
+exit:
+
+ SAFE_RELEASE(pStream);
+ SAFE_RELEASE(pWave);
+
+ return ntStatus;
+}
// ISSUE-2014/10/20 Add synchronization mechanism throughout this class
// ISSUE-2014/10/20 Add comment headers and commenting throughout
diff --git a/audio/sysvad/EndpointsCommon/minwavert.h b/audio/sysvad/EndpointsCommon/minwavert.h
index 4660cfa1..da31f172 100644
--- a/audio/sysvad/EndpointsCommon/minwavert.h
+++ b/audio/sysvad/EndpointsCommon/minwavert.h
@@ -148,11 +148,14 @@ private:
#endif // SYSVAD_BTH_BYPASS
};
+ AUDIOMODULE * m_pAudioModules;
+
protected:
PADAPTERCOMMON m_pAdapterCommon;
ULONG m_DeviceFlags;
eDeviceType m_DeviceType;
PPORTEVENTS m_pPortEvents;
+ PPORTCLSNOTIFICATIONS m_pPortClsNotifications;
PENDPOINT_MINIPAIR m_pMiniportPair;
@@ -231,7 +234,9 @@ public:
m_DeviceFormatsAndModes(MiniportPair->PinDeviceFormatsAndModes),
m_DeviceFormatsAndModesCount(MiniportPair->PinDeviceFormatsAndModesCount),
m_DeviceFlags(MiniportPair->DeviceFlags),
- m_pMiniportPair(MiniportPair)
+ m_pMiniportPair(MiniportPair),
+ m_pAudioModules(NULL),
+ m_pPortClsNotifications(NULL)
{
PAGED_CODE();
@@ -266,7 +271,6 @@ public:
}
}
-
#ifdef SYSVAD_BTH_BYPASS
if (IsBthHfpDevice())
{
@@ -316,6 +320,22 @@ public:
(
_In_ PPCPROPERTY_REQUEST PropertyRequest
);
+
+ NTSTATUS PropertyHandlerModulesListRequest
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerModuleCommand
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerModuleNotificationDeviceId
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
PADAPTERCOMMON GetAdapterCommObj()
{
@@ -629,8 +649,70 @@ protected:
ASSERT(!IsCellularDevice());
return KSPIN_WAVE_RENDER_SINK_OFFLOAD;
}
+
#pragma code_seg()
+ ULONG
+ GetAudioModuleDescriptorListCount()
+ {
+ return m_pMiniportPair->ModuleListCount;
+ }
+
+ const PAUDIOMODULE_DESCRIPTOR
+ GetAudioModuleDescriptor(
+ _In_ ULONG Index
+ )
+ {
+ ASSERT(Index < GetAudioModuleDescriptorListCount());
+ return &m_pMiniportPair->ModuleList[Index];
+ }
+
+ const PAUDIOMODULE_DESCRIPTOR
+ GetAudioModuleDescriptorList()
+ {
+ return m_pMiniportPair->ModuleList;
+ }
+
+ ULONG
+ GetAudioModuleListCount()
+ {
+ return GetAudioModuleDescriptorListCount();
+ }
+
+ AUDIOMODULE *
+ GetAudioModule(
+ _In_ ULONG Index
+ )
+ {
+ ASSERT(Index < GetAudioModuleListCount());
+ return &m_pAudioModules[Index];
+ }
+
+ AUDIOMODULE *
+ GetAudioModuleList()
+ {
+ return m_pAudioModules;
+ }
+
+ const GUID *
+ GetAudioModuleNotificationDeviceId()
+ {
+ return m_pMiniportPair->ModuleNotificationDeviceId;
+ }
+
+ NTSTATUS
+ AllocStreamAudioModules(
+ _In_ const GUID * SignalProcessingMode,
+ _Out_ AUDIOMODULE ** AudioModule,
+ _Out_ ULONG * AudioModuleCount
+ );
+
+ VOID
+ FreeStreamAudioModules(
+ _In_ AUDIOMODULE * AudioModule,
+ _In_ ULONG AudioModuleCount
+ );
+
#ifdef SYSVAD_BTH_BYPASS
public:
#pragma code_seg("PAGE")
diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.cpp b/audio/sysvad/EndpointsCommon/minwavertstream.cpp
index 58382639..1661b5fb 100644
--- a/audio/sysvad/EndpointsCommon/minwavertstream.cpp
+++ b/audio/sysvad/EndpointsCommon/minwavertstream.cpp
@@ -5,6 +5,7 @@
#include "minwavert.h"
#include "minwavertstream.h"
#include "UnittestData.h"
+#include "AudioModuleHelper.h"
#define MINWAVERTSTREAM_POOLTAG 'SRWM'
#pragma warning (disable : 4127)
@@ -34,8 +35,16 @@ Return Value:
--*/
{
PAGED_CODE();
+
if (NULL != m_pMiniport)
{
+ if (m_pAudioModules)
+ {
+ m_pMiniport->FreeStreamAudioModules(m_pAudioModules, m_AudioModuleCount);
+ m_pAudioModules = NULL;
+ m_AudioModuleCount = 0;
+ }
+
if (m_bUnregisterStream)
{
m_pMiniport->StreamClosed(m_ulPin, this);
@@ -181,6 +190,8 @@ Return Value:
m_SignalProcessingMode = SignalProcessingMode;
m_bEoSReceived = FALSE;
m_bLastBufferRendered = FALSE;
+ m_pAudioModules = NULL;
+ m_AudioModuleCount = 0;
#ifdef SYSVAD_BTH_BYPASS
m_ScoOpen = FALSE;
@@ -268,6 +279,17 @@ Return Value:
}
RtlZeroMemory(m_plPeakMeter, m_pWfExt->Format.nChannels * sizeof(LONG));
+ //
+ // Allocate stream audio module resources.
+ //
+ ntStatus = m_pMiniport->AllocStreamAudioModules(&SignalProcessingMode,
+ &m_pAudioModules,
+ &m_AudioModuleCount);
+ if (!NT_SUCCESS(ntStatus))
+ {
+ return ntStatus;
+ }
+
if (m_bCapture)
{
DWORD toneFrequency = 0;
@@ -784,6 +806,7 @@ Done:
//
// ISSUE-2014/10/4 Will this work correctly across pause/play?
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::GetReadPacket
(
_Out_ ULONG *PacketNumber,
@@ -854,7 +877,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket
// Compute and return timestamp corresponding to start of the available packet. In a real hardware
// driver, the timestamp would be computed in a driver and hardware specific manner. In this sample
- // driver, it is extrapolated from the sample driver's internal simulated position corrleation
+ // driver, it is extrapolated from the sample driver's internal simulated position correlation
// [m_ullLinearPosition @ m_ullDmaTimeStamp] and the sample's internal 64-bit packet counter, subtracting
// 1 from the packet counter to compute the time at the start of that last completed packet.
ULONGLONG linearPositionOfAvailablePacket = (packetCounter - 1) * (m_ulDmaBufferSize / m_ulNotificationsPerBuffer);
@@ -895,6 +918,7 @@ NTSTATUS CMiniportWaveRTStream::GetReadPacket
}
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::SetWritePacket
(
_In_ ULONG PacketNumber,
@@ -987,6 +1011,7 @@ NTSTATUS CMiniportWaveRTStream::SetWritePacket
//=============================================================================
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition
(
_Out_ KSAUDIO_PRESENTATION_POSITION *pPresentationPosition
@@ -1005,6 +1030,7 @@ NTSTATUS CMiniportWaveRTStream::GetOutputStreamPresentationPosition
//=============================================================================
#pragma code_seg()
+_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS CMiniportWaveRTStream::GetPacketCount
(
_Out_ ULONG *pPacketCount
@@ -1506,6 +1532,47 @@ Return Value:
#endif // SYSVAD_BTH_BYPASS
//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRTStream::PropertyHandlerModulesListRequest
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ // This specific APO->driver communication example is mainly added to show
+ // how this communication is done. The instance module list lives on the
+ // stream object and it can only have modules associated with the underline
+ // stream's pin.
+
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRTStream::PropertyHandlerModulesListRequest]"));
+
+ return AudioModule_GenericHandler_ModulesListRequest(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModulesListRequest
+
+//=============================================================================
+#pragma code_seg("PAGE")
+NTSTATUS
+CMiniportWaveRTStream::PropertyHandlerModuleCommand
+(
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+)
+{
+ PAGED_CODE();
+
+ DPF_ENTER(("[CMiniportWaveRTStream::PropertyHandlerModuleCommand]"));
+
+ return AudioModule_GenericHandler_ModuleCommand(
+ PropertyRequest,
+ GetAudioModuleList(),
+ GetAudioModuleListCount());
+} // PropertyHandlerModuleCommand
+
+//=============================================================================
#pragma code_seg()
void
TimerNotifyRT
@@ -1550,10 +1617,10 @@ TimerNotifyRT
goto End;
}
- // Carry forward the remainder of this division
- _this->m_hnsDPCTimeCarryForward = (hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward) % 10000;
+ // Carry forward the time greater than notification interval to adjust time to signal next buffer completion event accordingly.
+ _this->m_hnsDPCTimeCarryForward = hnsCurrentTime - _this->m_ullLastDPCTimeStamp + _this->m_hnsDPCTimeCarryForward - (_this->m_ulNotificationIntervalMs * 10000);
// Save the last time DPC ran at notification interval
- _this->m_ullLastDPCTimeStamp = (ULONG)hnsCurrentTime;
+ _this->m_ullLastDPCTimeStamp = hnsCurrentTime;
_this->UpdatePosition(qpc);
diff --git a/audio/sysvad/EndpointsCommon/minwavertstream.h b/audio/sysvad/EndpointsCommon/minwavertstream.h
index 405ae35e..3034d630 100644
--- a/audio/sysvad/EndpointsCommon/minwavertstream.h
+++ b/audio/sysvad/EndpointsCommon/minwavertstream.h
@@ -125,6 +125,8 @@ protected:
BOOLEAN m_bEoSReceived;
BOOLEAN m_bLastBufferRendered;
KSPIN_LOCK m_PositionSpinLock;
+ AUDIOMODULE * m_pAudioModules;
+ ULONG m_AudioModuleCount;
#ifdef SYSVAD_BTH_BYPASS
BOOLEAN m_ScoOpen;
@@ -227,10 +229,45 @@ public:
{
return m_SignalProcessingMode;
}
+
+ NTSTATUS PropertyHandlerModulesListRequest
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
+
+ NTSTATUS PropertyHandlerModuleCommand
+ (
+ _In_ PPCPROPERTY_REQUEST PropertyRequest
+ );
private:
+ //
// Helper functions.
+ //
+
+#pragma code_seg()
+ ULONG
+ GetAudioModuleListCount()
+ {
+ return m_AudioModuleCount;
+ }
+
+ AUDIOMODULE *
+ GetAudioModule(
+ _In_ ULONG Index
+ )
+ {
+ ASSERT(Index < GetAudioModuleListCount());
+ return &m_pAudioModules[Index];
+ }
+
+ AUDIOMODULE *
+ GetAudioModuleList()
+ {
+ return m_pAudioModules;
+ }
+
VOID WriteBytes
(
_In_ ULONG ByteDisplacement
diff --git a/audio/sysvad/EndpointsCommon/sources b/audio/sysvad/EndpointsCommon/sources
new file mode 100644
index 00000000..ab930dbd
--- /dev/null
+++ b/audio/sysvad/EndpointsCommon/sources
@@ -0,0 +1,46 @@
+
+# Copyright (c) Microsoft Corporation. All rights reserved.
+
+
+TARGETNAME=EndpointsCommon
+TARGETTYPE=LIBRARY
+KM_LIBRARY=1
+
+INCLUDES= \
+ $(DDK_INC_PATH); \
+ ..
+
+
+C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_ -DSYSVAD_BTH_BYPASS
+#C_DEFINES = $(C_DEFINES) -D_USE_WAVERT_
+
+DDK_TARGET_PLATFORM=Universal
+
+#
+# Indicate to the WDK that this sample only supports Win10[+]
+#
+MINIMUM_NT_TARGET_VERSION=$(_NT_TARGET_VERSION_WINTHRESHOLD)
+
+#
+# Audio driver is a KMDF miniport.
+#
+KMDF_VERSION_MAJOR=1
+
+
+SOURCES=$(SOURCES) \
+ mintopo.cpp \
+ minwavert.cpp \
+ minwavertstream.cpp \
+ MiniportAudioEngineNode.cpp\
+ MiniportStreamAudioEngineNode.cpp\
+ micarraytopo.cpp \
+ speakertopo.cpp \
+ speakerhptopo.cpp \
+ bthhfptopo.cpp \
+ bthhfpmictopo.cpp \
+ bthhfpspeakertopo.cpp \
+ bthhfpminwavert.cpp \
+ AudioModuleHelper.cpp \
+
+
+
diff --git a/audio/sysvad/EndpointsCommon/speakerhpwavtable.h b/audio/sysvad/EndpointsCommon/speakerhpwavtable.h
index 2f36ac06..66fc9c8a 100644
--- a/audio/sysvad/EndpointsCommon/speakerhpwavtable.h
+++ b/audio/sysvad/EndpointsCommon/speakerhpwavtable.h
@@ -15,6 +15,9 @@ Abstract:
#ifndef _SYSVAD_SPEAKERHPWAVTABLE_H_
#define _SYSVAD_SPEAKERHPWAVTABLE_H_
+#include "AudioModule0.h"
+#include "AudioModule1.h"
+#include "AudioModule2.h"
// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
@@ -579,6 +582,33 @@ PKSDATARANGE SpeakerHpPinDataRangePointersBridge[] =
//=============================================================================
static
+PCPROPERTY_ITEM PropertiesSpeakerHpHostPin[] =
+{
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpHostPin, PropertiesSpeakerHpHostPin);
+
+//=============================================================================
+
+static
PCPROPERTY_ITEM PropertiesSpeakerHpOffloadPin[] =
{
{
@@ -592,7 +622,25 @@ PCPROPERTY_ITEM PropertiesSpeakerHpOffloadPin[] =
KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_OffloadPin
- }
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
};
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpOffloadPin, PropertiesSpeakerHpOffloadPin);
@@ -606,7 +654,7 @@ PCPIN_DESCRIPTOR SpeakerHpWaveMiniportPins[] =
SPEAKERHP_MAX_INPUT_SYSTEM_STREAMS,
SPEAKERHP_MAX_INPUT_SYSTEM_STREAMS,
0,
- NULL,
+ &AutomationSpeakerHpHostPin, // AutomationTable
{
0,
NULL,
@@ -722,9 +770,84 @@ PCPROPERTY_ITEM PropertiesSpeakerHpWaveFilter[] =
KSPROPERTY_PIN_PROPOSEDATAFORMAT,
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+};
+
+//
+// Endpoint audio module list.
+//
+static
+AUDIOMODULE_DESCRIPTOR SpeakerHpModulesWaveFilter[] =
+{
+ { // 0
+ &AudioModule0Id, // class id.
+ &NULL_GUID, // generic, mode independent.
+ L"Generic system module",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE0_MAJOR,
+ AUDIOMODULE0_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE0_CONTEXT),
+ AudioModule0_InitClass,
+ AudioModule0_InitInstance,
+ AudioModule0_Cleanup,
+ AudioModule0_Handler
+ },
+ { // 1
+ &AudioModule1Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_MOVIE,
+ L"Speaker HP endpoint, EQ effect module, Movie mode",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE1_MAJOR,
+ AUDIOMODULE1_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE1_CONTEXT),
+ AudioModule1_InitClass,
+ AudioModule1_InitInstance,
+ AudioModule1_Cleanup,
+ AudioModule1_Handler
+ },
+ { // 2
+ &AudioModule2Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
+ L"Speaker HP endpoint, Echo Cancellation effect module, Default mode",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE2_MAJOR,
+ AUDIOMODULE2_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE2_CONTEXT),
+ AudioModule2_InitClass,
+ AudioModule2_InitInstance,
+ AudioModule2_Cleanup,
+ AudioModule2_Handler
}
};
+//
+// Audio module notification device id.
+// NOTE: do not use this guid for real driver, generate a new one.
+//
+const GUID SpeakerHpModuleNotificationDeviceId =
+{0x3A66BE17,0x5440,0x48E7,0x83,0x76,0xB7,0x5A,0x0B,0x1A,0x92,0x2D};
+
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHpWaveFilter, PropertiesSpeakerHpWaveFilter);
//=============================================================================
diff --git a/audio/sysvad/EndpointsCommon/speakerwavtable.h b/audio/sysvad/EndpointsCommon/speakerwavtable.h
index cb2c2481..94f7863b 100644
--- a/audio/sysvad/EndpointsCommon/speakerwavtable.h
+++ b/audio/sysvad/EndpointsCommon/speakerwavtable.h
@@ -16,6 +16,8 @@ Abstract:
#define _SYSVAD_SPEAKERWAVTABLE_H_
#include "SysVadShared.h"
+#include "AudioModule0.h"
+#include "AudioModule1.h"
// To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM)
@@ -581,6 +583,33 @@ PKSDATARANGE SpeakerPinDataRangePointersBridge[] =
//=============================================================================
static
+PCPROPERTY_ITEM PropertiesSpeakerHostPin[] =
+{
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+};
+
+DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerHostPin, PropertiesSpeakerHostPin);
+
+//=============================================================================
+
+static
PCPROPERTY_ITEM PropertiesSpeakerOffloadPin[] =
{
{
@@ -594,7 +623,25 @@ PCPROPERTY_ITEM PropertiesSpeakerOffloadPin[] =
KSPROPERTY_OFFLOAD_PIN_VERIFY_STREAM_OBJECT_POINTER, // define properties
KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_OffloadPin
- }
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_GenericPin
+ },
};
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerOffloadPin, PropertiesSpeakerOffloadPin);
@@ -608,7 +655,7 @@ PCPIN_DESCRIPTOR SpeakerWaveMiniportPins[] =
SPEAKER_MAX_INPUT_SYSTEM_STREAMS,
SPEAKER_MAX_INPUT_SYSTEM_STREAMS,
0,
- NULL,
+ &AutomationSpeakerHostPin, // AutomationTable
{
0,
NULL,
@@ -730,9 +777,84 @@ PCPROPERTY_ITEM PropertiesSpeakerWaveFilter[] =
KSPROPERTY_SYSVAD_DEFAULTSTREAMEFFECTS,
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_DESCRIPTORS,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_COMMAND,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+ {
+ &KSPROPSETID_AudioModule,
+ KSPROPERTY_AUDIOMODULE_NOTIFICATION_DEVICE_ID,
+ KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
+ PropertyHandler_WaveFilter
+ },
+};
+
+//
+// Endpoint audio module list.
+//
+static
+AUDIOMODULE_DESCRIPTOR SpeakerModulesWaveFilter[] =
+{
+ { // 0
+ &AudioModule0Id, // class id.
+ &NULL_GUID, // generic, mode independent.
+ L"Generic system module",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE0_MAJOR,
+ AUDIOMODULE0_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE0_CONTEXT),
+ AudioModule0_InitClass,
+ AudioModule0_InitInstance,
+ AudioModule0_Cleanup,
+ AudioModule0_Handler
+ },
+ { // 1
+ &AudioModule1Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_MOVIE,
+ L"Speaker endpoint, EQ effect module, Movie mode",
+ AUDIOMODULE_INSTANCE_ID(0,0),
+ AUDIOMODULE1_MAJOR,
+ AUDIOMODULE1_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE1_CONTEXT),
+ AudioModule1_InitClass,
+ AudioModule1_InitInstance,
+ AudioModule1_Cleanup,
+ AudioModule1_Handler
+ },
+ { // 2
+ &AudioModule1Id, // class id.
+ &AUDIO_SIGNALPROCESSINGMODE_DEFAULT,
+ L"Speaker endpoint, EQ effect module, Default mode",
+ AUDIOMODULE_INSTANCE_ID(1,0),
+ AUDIOMODULE1_MAJOR,
+ AUDIOMODULE1_MINOR,
+ AUDIOMODULE_DESCRIPTOR_FLAG_NONE,
+ sizeof(AUDIOMODULE1_CONTEXT),
+ AudioModule1_InitClass,
+ AudioModule1_InitInstance,
+ AudioModule1_Cleanup,
+ AudioModule1_Handler
}
};
+//
+// Audio module notification device id.
+// NOTE: do not use this guid for real driver, generate a new one.
+//
+const GUID SpeakerModuleNotificationDeviceId =
+{0xC01C987A,0x30A9,0x4DB7,0x8D,0x69,0x69,0x6C,0xFF,0x41,0xE4,0xB9};
+
DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerWaveFilter, PropertiesSpeakerWaveFilter);
//=============================================================================