diff options
Diffstat (limited to 'audio/simpleaudiosample/Source/Main/basetopo.cpp')
| -rw-r--r-- | audio/simpleaudiosample/Source/Main/basetopo.cpp | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/audio/simpleaudiosample/Source/Main/basetopo.cpp b/audio/simpleaudiosample/Source/Main/basetopo.cpp new file mode 100644 index 00000000..b29a9bb1 --- /dev/null +++ b/audio/simpleaudiosample/Source/Main/basetopo.cpp @@ -0,0 +1,688 @@ +/*++ + +Copyright (c) Microsoft Corporation All Rights Reserved + +Module Name: + + basetopo.cpp + +Abstract: + + Implementation of topology miniport. This the base class for + all simple audio sample drivers +--*/ + +//4127: conditional expression is constant +#pragma warning (disable : 4127) + +#include "definitions.h" +#include "basetopo.h" + +//============================================================================= +#pragma code_seg("PAGE") +CMiniportTopologySimpleAudioSample::CMiniportTopologySimpleAudioSample +( + _In_ PCFILTER_DESCRIPTOR *FilterDesc, + _In_ USHORT DeviceMaxChannels +) +/*++ + +Routine Description: + + Topology miniport constructor + +Arguments: + + FilterDesc - + + DeviceMaxChannels - + +Return Value: + + void + +--*/ +{ + PAGED_CODE(); + + DPF_ENTER(("[%s]",__FUNCTION__)); + + m_AdapterCommon = NULL; + + ASSERT(FilterDesc != NULL); + m_FilterDescriptor = FilterDesc; + m_PortEvents = NULL; + + ASSERT(DeviceMaxChannels > 0); + m_DeviceMaxChannels = DeviceMaxChannels; +} // CMiniportTopologySimpleAudioSample + +CMiniportTopologySimpleAudioSample::~CMiniportTopologySimpleAudioSample +( + void +) +/*++ + +Routine Description: + + Topology miniport destructor + +Arguments: + +Return Value: + + void + +--*/ +{ + PAGED_CODE(); + + DPF_ENTER(("[%s]",__FUNCTION__)); + + SAFE_RELEASE(m_AdapterCommon); + SAFE_RELEASE(m_PortEvents); +} // ~CMiniportTopologySimpleAudioSample + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopologySimpleAudioSample::DataRangeIntersection +( + _In_ ULONG PinId, + _In_ PKSDATARANGE ClientDataRange, + _In_ PKSDATARANGE MyDataRange, + _In_ ULONG OutputBufferLength, + _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength) + PVOID ResultantFormat OPTIONAL, + _Out_ PULONG ResultantFormatLength +) +/*++ + +Routine Description: + + The DataRangeIntersection function determines the highest + quality intersection of two data ranges. Topology miniport does nothing. + +Arguments: + + PinId - Pin for which data intersection is being determined. + + ClientDataRange - Pointer to KSDATARANGE structure which contains the data range + submitted by client in the data range intersection property + request + + MyDataRange - Pin's data range to be compared with client's data range + + OutputBufferLength - Size of the buffer pointed to by the resultant format + parameter + + ResultantFormat - Pointer to value where the resultant format should be + returned + + ResultantFormatLength - Actual length of the resultant format that is placed + at ResultantFormat. This should be less than or equal + to OutputBufferLength + +Return Value: + + NT status code. + +--*/ +{ + UNREFERENCED_PARAMETER(PinId); + UNREFERENCED_PARAMETER(ClientDataRange); + UNREFERENCED_PARAMETER(MyDataRange); + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(ResultantFormat); + UNREFERENCED_PARAMETER(ResultantFormatLength); + + PAGED_CODE(); + + DPF_ENTER(("[%s]",__FUNCTION__)); + + return (STATUS_NOT_IMPLEMENTED); +} // DataRangeIntersection + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopologySimpleAudioSample::GetDescription +( + _Out_ PPCFILTER_DESCRIPTOR * OutFilterDescriptor +) +/*++ + +Routine Description: + + The GetDescription function gets a pointer to a filter description. + It provides a location to deposit a pointer in miniport's description + structure. This is the placeholder for the FromNode or ToNode fields in + connections which describe connections to the filter's pins + +Arguments: + + OutFilterDescriptor - Pointer to the filter description. + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(OutFilterDescriptor); + + DPF_ENTER(("[%s]",__FUNCTION__)); + + *OutFilterDescriptor = m_FilterDescriptor; + + return (STATUS_SUCCESS); +} // GetDescription + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopologySimpleAudioSample::Init +( + _In_ PUNKNOWN UnknownAdapter_, + _In_ PPORTTOPOLOGY Port_ +) +/*++ + +Routine Description: + + Initializes the topology miniport. + +Arguments: + + UnknownAdapter - + + Port_ - Pointer to topology port + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + ASSERT(UnknownAdapter_); + ASSERT(Port_); + + DPF_ENTER(("[CMiniportTopologySimpleAudioSample::Init]")); + + NTSTATUS ntStatus; + + ntStatus = + UnknownAdapter_->QueryInterface( + IID_IAdapterCommon, + (PVOID *) &m_AdapterCommon); + + if (NT_SUCCESS(ntStatus)) + { + // + // Get the port event interface. + // + ntStatus = Port_->QueryInterface( + IID_IPortEvents, + (PVOID *)&m_PortEvents); + } + + if (NT_SUCCESS(ntStatus)) + { + m_AdapterCommon->MixerReset(); + } + + if (!NT_SUCCESS(ntStatus)) + { + // clean up AdapterCommon + SAFE_RELEASE(m_AdapterCommon); + SAFE_RELEASE(m_PortEvents); + } + + return ntStatus; +} // Init + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopologySimpleAudioSample::PropertyHandlerGeneric +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Handles all properties for this miniport. + +Arguments: + + PropertyRequest - property request structure + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + switch (PropertyRequest->PropertyItem->Id) + { + case KSPROPERTY_AUDIO_VOLUMELEVEL: + ntStatus = PropertyHandler_Volume( + m_AdapterCommon, + PropertyRequest, + m_DeviceMaxChannels); + break; + + case KSPROPERTY_AUDIO_MUTE: + ntStatus = PropertyHandler_Mute( + m_AdapterCommon, + PropertyRequest, + m_DeviceMaxChannels); + break; + + case KSPROPERTY_AUDIO_PEAKMETER2: + ntStatus = PropertyHandler_PeakMeter2( + m_AdapterCommon, + PropertyRequest, + m_DeviceMaxChannels); + break; + + case KSPROPERTY_AUDIO_CPU_RESOURCES: + ntStatus = PropertyHandler_CpuResources(PropertyRequest); + break; + + case KSPROPERTY_AUDIO_MUX_SOURCE: + ntStatus = PropertyHandlerMuxSource(PropertyRequest); + break; + + case KSPROPERTY_AUDIO_DEV_SPECIFIC: + ntStatus = PropertyHandlerDevSpecific(PropertyRequest); + break; + + default: + DPF(D_TERSE, ("[PropertyHandlerGeneric: Invalid Device Request]")); + } + + return ntStatus; +} // PropertyHandlerGeneric + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopologySimpleAudioSample::PropertyHandlerMuxSource +( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + PropertyHandler for KSPROPERTY_AUDIO_MUX_SOURCE. + +Arguments: + + PropertyRequest - property request structure + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + DPF_ENTER(("[%s]",__FUNCTION__)); + + NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; + + // + // Validate node + // This property is only valid for WAVEIN_MUX node. + // + // TODO if (WAVEIN_MUX == PropertyRequest->Node) + { + if (PropertyRequest->ValueSize >= sizeof(ULONG)) + { + PULONG pulMuxValue = PULONG(PropertyRequest->Value); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + *pulMuxValue = m_AdapterCommon->MixerMuxRead(); + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) + { + m_AdapterCommon->MixerMuxWrite(*pulMuxValue); + ntStatus = STATUS_SUCCESS; + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + ntStatus = + PropertyHandler_BasicSupport + ( + PropertyRequest, + KSPROPERTY_TYPE_ALL, + VT_I4 + ); + } + } + else + { + DPF(D_TERSE, ("[PropertyHandlerMuxSource - Invalid parameter]")); + ntStatus = STATUS_INVALID_PARAMETER; + } + } + + return ntStatus; +} // PropertyHandlerMuxSource + +//============================================================================= +#pragma code_seg("PAGE") +NTSTATUS +CMiniportTopologySimpleAudioSample::PropertyHandlerDevSpecific( + _In_ PPCPROPERTY_REQUEST PropertyRequest +) +/*++ + +Routine Description: + + Property handler for KSPROPERTY_AUDIO_DEV_SPECIFIC + +Arguments: + + PropertyRequest - property request structure + +Return Value: + + NT status code. + +--*/ +{ + PAGED_CODE(); + + DPF_ENTER(("[%s]",__FUNCTION__)); + + NTSTATUS ntStatus=STATUS_SUCCESS; + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT) + { + if( DEV_SPECIFIC_VT_BOOL == PropertyRequest->Node ) + { + ntStatus = PropertyHandler_BasicSupport(PropertyRequest,KSPROPERTY_TYPE_ALL,VT_BOOL); + } + else + { + ULONG ExpectedSize = sizeof( KSPROPERTY_DESCRIPTION ) + + sizeof( KSPROPERTY_MEMBERSHEADER ) + + sizeof( KSPROPERTY_BOUNDS_LONG ); + DWORD ulPropTypeSetId; + + if( DEV_SPECIFIC_VT_I4 == PropertyRequest->Node ) + { + ulPropTypeSetId = VT_I4; + } + else if ( DEV_SPECIFIC_VT_UI4 == PropertyRequest->Node ) + { + ulPropTypeSetId = VT_UI4; + } + else + { + ulPropTypeSetId = VT_ILLEGAL; + ntStatus = STATUS_INVALID_PARAMETER; + } + + if( NT_SUCCESS(ntStatus)) + { + if ( !PropertyRequest->ValueSize ) + { + PropertyRequest->ValueSize = ExpectedSize; + ntStatus = STATUS_BUFFER_OVERFLOW; + } + else if (PropertyRequest->ValueSize >= sizeof(KSPROPERTY_DESCRIPTION)) + { + // if return buffer can hold a KSPROPERTY_DESCRIPTION, return it + // + PKSPROPERTY_DESCRIPTION PropDesc = PKSPROPERTY_DESCRIPTION(PropertyRequest->Value); + + PropDesc->AccessFlags = KSPROPERTY_TYPE_ALL; + PropDesc->DescriptionSize = ExpectedSize; + PropDesc->PropTypeSet.Set = KSPROPTYPESETID_General; + PropDesc->PropTypeSet.Id = ulPropTypeSetId; + PropDesc->PropTypeSet.Flags = 0; + PropDesc->MembersListCount = 0; + PropDesc->Reserved = 0; + + if ( PropertyRequest->ValueSize >= ExpectedSize ) + { + // Extra information to return + PropDesc->MembersListCount = 1; + + PKSPROPERTY_MEMBERSHEADER MembersHeader = ( PKSPROPERTY_MEMBERSHEADER )( PropDesc + 1); + MembersHeader->MembersFlags = KSPROPERTY_MEMBER_RANGES; + MembersHeader->MembersCount = 1; + MembersHeader->MembersSize = sizeof( KSPROPERTY_BOUNDS_LONG ); + MembersHeader->Flags = 0; + + PKSPROPERTY_BOUNDS_LONG PeakMeterBounds = (PKSPROPERTY_BOUNDS_LONG)( MembersHeader + 1); + if(VT_I4 == ulPropTypeSetId ) + { + PeakMeterBounds->SignedMinimum = 0; + PeakMeterBounds->SignedMaximum = 0x7fffffff; + } + else + { + PeakMeterBounds->UnsignedMinimum = 0; + PeakMeterBounds->UnsignedMaximum = 0xffffffff; + } + + // set the return value size + PropertyRequest->ValueSize = ExpectedSize; + } + else + { + // No extra information to return. + PropertyRequest->ValueSize = sizeof(KSPROPERTY_DESCRIPTION); + } + + ntStatus = STATUS_SUCCESS; + } + else if (PropertyRequest->ValueSize >= sizeof(ULONG)) + { + // if return buffer can hold a ULONG, return the access flags + // + *(PULONG(PropertyRequest->Value)) = KSPROPERTY_TYPE_ALL; + + PropertyRequest->ValueSize = sizeof(ULONG); + ntStatus = STATUS_SUCCESS; + } + else + { + PropertyRequest->ValueSize = 0; + ntStatus = STATUS_BUFFER_TOO_SMALL; + } + } + } + } + else + { + // switch on node id + switch( PropertyRequest->Node ) + { + case DEV_SPECIFIC_VT_BOOL: + { + PBOOL pbDevSpecific; + + ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(BOOL), 0); + + if (NT_SUCCESS(ntStatus)) + { + pbDevSpecific = PBOOL (PropertyRequest->Value); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + *pbDevSpecific = m_AdapterCommon->bDevSpecificRead(); + PropertyRequest->ValueSize = sizeof(BOOL); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) + { + m_AdapterCommon->bDevSpecificWrite(*pbDevSpecific); + } + else + { + ntStatus = STATUS_INVALID_PARAMETER; + } + } + } + break; + case DEV_SPECIFIC_VT_I4: + { + INT* piDevSpecific; + + ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(int), 0); + + if (NT_SUCCESS(ntStatus)) + { + piDevSpecific = PINT (PropertyRequest->Value); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + *piDevSpecific = m_AdapterCommon->iDevSpecificRead(); + PropertyRequest->ValueSize = sizeof(int); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) + { + m_AdapterCommon->iDevSpecificWrite(*piDevSpecific); + } + else + { + ntStatus = STATUS_INVALID_PARAMETER; + } + } + } + break; + case DEV_SPECIFIC_VT_UI4: + { + UINT* puiDevSpecific; + + ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(UINT), 0); + + if (NT_SUCCESS(ntStatus)) + { + puiDevSpecific = PUINT (PropertyRequest->Value); + + if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET) + { + *puiDevSpecific = m_AdapterCommon->uiDevSpecificRead(); + PropertyRequest->ValueSize = sizeof(UINT); + } + else if (PropertyRequest->Verb & KSPROPERTY_TYPE_SET) + { + m_AdapterCommon->uiDevSpecificWrite(*puiDevSpecific); + } + else + { + ntStatus = STATUS_INVALID_PARAMETER; + } + } + } + break; + default: + ntStatus = STATUS_INVALID_PARAMETER; + break; + } + + + if( !NT_SUCCESS(ntStatus)) + { + DPF(D_TERSE, ("[%s - ntStatus=0x%08x]",__FUNCTION__,ntStatus)); + } + } + + return ntStatus; +} // PropertyHandlerDevSpecific + +//============================================================================= +#pragma code_seg("PAGE") +VOID +CMiniportTopologySimpleAudioSample::AddEventToEventList +( + _In_ PKSEVENT_ENTRY EventEntry +) +/*++ + +Routine Description: + + The AddEventToEventList method adds an event to the port driver's event list + +Arguments: + + EventEntry - + +--*/ +{ + PAGED_CODE(); + DPF_ENTER(("[CMiniportTopology::AddEventToEventList]")); + + ASSERT(m_PortEvents != NULL); + + m_PortEvents->AddEventToEventList(EventEntry); +} + +//============================================================================= +#pragma code_seg() +VOID +CMiniportTopologySimpleAudioSample::GenerateEventList +( + _In_opt_ GUID *Set, + _In_ ULONG EventId, + _In_ BOOL PinEvent, + _In_ ULONG PinId, + _In_ BOOL NodeEvent, + _In_ ULONG NodeId +) +/*++ + +Routine Description: + + The GenerateEventList method notifies clients through the port driver's list + of event entries that a particular event has occurred. + +Arguments: + + Set - + + EventId - + + PinEvent - + + PinId - + + NodeEvent - + + NodeId - + +--*/ +{ + DPF_ENTER(("[CMiniportTopologySimpleAudioSample::GenerateEventList]")); + + ASSERT(m_PortEvents != NULL); + + m_PortEvents->GenerateEventList( + Set, + EventId, + PinEvent, + PinId, + NodeEvent, + NodeId); +} + +#pragma code_seg() |
