diff options
| author | Girish Pattabiraman <[email protected]> | 2017-05-03 15:02:49 -0700 |
|---|---|---|
| committer | Girish Pattabiraman <[email protected]> | 2017-05-03 17:20:15 -0700 |
| commit | b9027f2b8124f5853dac4355ff4d9e85379e0e56 (patch) | |
| tree | 33487ba551e9e53ba5a000afc2ad8860892ef2fa /audio/sysvad/EndpointsCommon | |
| parent | 32dc5459e78107ce48412eef3653370f32274561 (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.h | 297 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/AudioModule1.h | 312 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/AudioModule2.h | 296 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/AudioModuleHelper.cpp | 644 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/AudioModuleHelper.h | 95 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj | 1 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/EndpointsCommon.vcxproj.Filters | 62 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/MiniportStreamAudioEngineNode.cpp | 1 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/minwavert.cpp | 427 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/minwavert.h | 86 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/minwavertstream.cpp | 75 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/minwavertstream.h | 37 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/sources | 46 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/speakerhpwavtable.h | 127 | ||||
| -rw-r--r-- | audio/sysvad/EndpointsCommon/speakerwavtable.h | 126 |
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); //============================================================================= |
