📄 basewave.cpp
字号:
/*++
Copyright (c) 1997-2000 Microsoft Corporation All Rights Reserved
Module Name:
basewave.cpp
Abstract:
Implementation of wavecyclic miniport.
--*/
#include <msvad.h>
#include "common.h"
#include "basewave.h"
//=============================================================================
// CMiniportWaveCyclicMSVAD
//=============================================================================
//=============================================================================
#pragma code_seg("PAGE")
CMiniportWaveCyclicMSVAD::CMiniportWaveCyclicMSVAD
(
void
)
/*++
Routine Description:
Constructor for wavecyclic miniport.
Arguments:
Return Value:
--*/
{
PAGED_CODE();
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::CMiniportWaveCyclicMSVAD]"));
// Initialize members.
//
m_AdapterCommon = NULL;
m_Port = NULL;
m_FilterDescriptor = NULL;
m_NotificationInterval = 0;
m_SamplingFrequency = 0;
m_ServiceGroup = NULL;
m_MaxDmaBufferSize = DMA_BUFFER_SIZE;
m_MaxOutputStreams = 0;
m_MaxInputStreams = 0;
m_MaxTotalStreams = 0;
m_MinChannels = 0;
m_MaxChannelsPcm = 0;
m_MinBitsPerSamplePcm = 0;
m_MaxBitsPerSamplePcm = 0;
m_MinSampleRatePcm = 0;
m_MaxSampleRatePcm = 0;
} // CMiniportWaveCyclicMSVAD
//=============================================================================
CMiniportWaveCyclicMSVAD::~CMiniportWaveCyclicMSVAD
(
void
)
/*++
Routine Description:
Destructor for wavecyclic miniport
Arguments:
Return Value:
--*/
{
PAGED_CODE();
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::~CMiniportWaveCyclicMSVAD]"));
if (m_Port)
{
m_Port->Release();
}
if (m_ServiceGroup)
{
m_ServiceGroup->Release();
}
if (m_AdapterCommon)
{
m_AdapterCommon->Release();
}
} // ~CMiniportWaveCyclicMSVAD
//=============================================================================
STDMETHODIMP
CMiniportWaveCyclicMSVAD::GetDescription
(
OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
)
/*++
Routine Description:
The GetDescription function gets a pointer to a filter description.
The descriptor is defined in wavtable.h for each MSVAD sample.
Arguments:
OutFilterDescriptor - Pointer to the filter description
Return Value:
NT status code.
--*/
{
PAGED_CODE();
ASSERT(OutFilterDescriptor);
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::GetDescription]"));
*OutFilterDescriptor = m_FilterDescriptor;
return (STATUS_SUCCESS);
} // GetDescription
//=============================================================================
STDMETHODIMP
CMiniportWaveCyclicMSVAD::Init
(
IN PUNKNOWN UnknownAdapter_,
IN PRESOURCELIST ResourceList_,
IN PPORTWAVECYCLIC Port_
)
/*++
Routine Description:
Arguments:
UnknownAdapter_ - pointer to adapter common.
ResourceList_ - resource list. MSVAD does not use resources.
Port_ - pointer to the port
Return Value:
NT status code.
--*/
{
PAGED_CODE();
ASSERT(UnknownAdapter_);
ASSERT(Port_);
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::Init]"));
// AddRef() is required because we are keeping this pointer.
//
m_Port = Port_;
m_Port->AddRef();
// We want the IAdapterCommon interface on the adapter common object,
// which is given to us as a IUnknown. The QueryInterface call gives us
// an AddRefed pointer to the interface we want.
//
NTSTATUS ntStatus =
UnknownAdapter_->QueryInterface
(
IID_IAdapterCommon,
(PVOID *) &m_AdapterCommon
);
if (NT_SUCCESS(ntStatus))
{
KeInitializeMutex(&m_SampleRateSync, 1);
ntStatus = PcNewServiceGroup(&m_ServiceGroup, NULL);
if (NT_SUCCESS(ntStatus))
{
m_AdapterCommon->SetWaveServiceGroup(m_ServiceGroup);
}
}
if (!NT_SUCCESS(ntStatus))
{
// clean up AdapterCommon
//
if (m_AdapterCommon)
{
// clean up the service group
//
if (m_ServiceGroup)
{
m_AdapterCommon->SetWaveServiceGroup(NULL);
m_ServiceGroup->Release();
m_ServiceGroup = NULL;
}
m_AdapterCommon->Release();
m_AdapterCommon = NULL;
}
// release the port
//
m_Port->Release();
m_Port = NULL;
}
return ntStatus;
} // Init
//=============================================================================
NTSTATUS
CMiniportWaveCyclicMSVAD::PropertyHandlerCpuResources
(
IN PPCPROPERTY_REQUEST PropertyRequest
)
/*++
Routine Description:
Processes KSPROPERTY_AUDIO_CPURESOURCES
Arguments:
PropertyRequest - property request structure
Return Value:
NT status code.
--*/
{
PAGED_CODE();
ASSERT(PropertyRequest);
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::PropertyHandlerCpuResources]"));
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
if (PropertyRequest->Verb & KSPROPERTY_TYPE_GET)
{
ntStatus = ValidatePropertyParams(PropertyRequest, sizeof(LONG), 0);
if (NT_SUCCESS(ntStatus))
{
*(PLONG(PropertyRequest->Value)) = KSAUDIO_CPU_RESOURCES_NOT_HOST_CPU;
PropertyRequest->ValueSize = sizeof(LONG);
ntStatus = STATUS_SUCCESS;
}
}
else if (PropertyRequest->Verb & KSPROPERTY_TYPE_BASICSUPPORT)
{
ntStatus =
PropertyHandler_BasicSupport
(
PropertyRequest,
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT,
VT_I4
);
}
return ntStatus;
} // PropertyHandlerCpuResources
//=============================================================================
NTSTATUS
CMiniportWaveCyclicMSVAD::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();
ASSERT(PropertyRequest);
ASSERT(PropertyRequest->PropertyItem);
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
switch (PropertyRequest->PropertyItem->Id)
{
case KSPROPERTY_AUDIO_CPU_RESOURCES:
ntStatus = PropertyHandlerCpuResources(PropertyRequest);
break;
default:
DPF(D_TERSE, ("[PropertyHandlerGeneric: Invalid Device Request]"));
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}
return ntStatus;
} // PropertyHandlerGeneric
//=============================================================================
NTSTATUS
CMiniportWaveCyclicMSVAD::ValidateFormat
(
IN PKSDATAFORMAT pDataFormat
)
/*++
Routine Description:
Validates that the given dataformat is valid.
This version of the driver only supports PCM.
Arguments:
pDataFormat - The dataformat for validation.
Return Value:
NT status code.
--*/
{
PAGED_CODE();
ASSERT(pDataFormat);
DPF_ENTER(("[CMiniportWaveCyclicMSVAD::ValidateFormat]"));
NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
PWAVEFORMATEX pwfx;
pwfx = GetWaveFormatEx(pDataFormat);
if (pwfx)
{
if (IS_VALID_WAVEFORMATEX_GUID(&pDataFormat->SubFormat))
{
USHORT wfxID = EXTRACT_WAVEFORMATEX_ID(&pDataFormat->SubFormat);
switch (wfxID)
{
case WAVE_FORMAT_PCM:
{
switch (pwfx->wFormatTag)
{
case WAVE_FORMAT_PCM:
{
ntStatus = ValidatePcm(pwfx);
break;
}
}
break;
}
default:
DPF(D_TERSE, ("Invalid format EXTRACT_WAVEFORMATEX_ID!"));
break;
}
}
else
{
DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") );
}
}
return ntStatus;
} // ValidateFormat
//-----------------------------------------------------------------------------
NTSTATUS
CMiniportWaveCyclicMSVAD::ValidatePcm
(
IN PWAVEFORMATEX pWfx
)
/*++
Routine Description:
Given a waveformatex and format size validates that the format is in device
datarange.
Arguments:
pWfx - wave format structure.
Return Value:
NT status code.
--*/
{
PAGED_CODE();
DPF_ENTER(("CMiniportWaveCyclicMSVAD::ValidatePcm"));
if
(
pWfx &&
(pWfx->cbSize == 0) &&
(pWfx->nChannels >= m_MinChannels) &&
(pWfx->nChannels <= m_MaxChannelsPcm) &&
(pWfx->nSamplesPerSec >= m_MinSampleRatePcm) &&
(pWfx->nSamplesPerSec <= m_MaxSampleRatePcm) &&
(pWfx->wBitsPerSample >= m_MinBitsPerSamplePcm) &&
(pWfx->wBitsPerSample <= m_MaxBitsPerSamplePcm)
)
{
return STATUS_SUCCESS;
}
DPF(D_TERSE, ("Invalid PCM format"));
return STATUS_INVALID_PARAMETER;
} // ValidatePcm
//=============================================================================
// CMiniportWaveCyclicStreamMSVAD
//=============================================================================
CMiniportWaveCyclicStreamMSVAD::CMiniportWaveCyclicStreamMSVAD
(
void
)
{
m_pMiniport = NULL;
m_fCapture = FALSE;
m_fFormat16Bit = FALSE;
m_fFormatStereo = FALSE;
m_ksState = KSSTATE_STOP;
m_ulPin = (ULONG)-1;
m_pDpc = NULL;
m_pTimer = NULL;
m_fDmaActive = FALSE;
m_ulDmaPosition = 0;
m_pvDmaBuffer = NULL;
m_ulDmaBufferSize = 0;
m_ulDmaMovementRate = 0;
m_ullDmaTimeStamp = 0;
}
//=============================================================================
CMiniportWaveCyclicStreamMSVAD::~CMiniportWaveCyclicStreamMSVAD
(
void
)
/*++
Routine Description:
Destructor for wavecyclic stream
Arguments:
void
Return Value:
--*/
{
PAGED_CODE();
DPF_ENTER(("[CMiniportWaveCyclicStreamMS::~CMiniportWaveCyclicStreamMS]"));
if (m_pTimer)
{
KeCancelTimer(m_pTimer);
ExFreePool(m_pTimer);
}
if (m_pDpc)
{
ExFreePool( m_pDpc );
}
// Free the DMA buffer
//
FreeBuffer();
} // ~CMiniportWaveCyclicStreamMSVAD
//=============================================================================
NTSTATUS
CMiniportWaveCyclicStreamMSVAD::Init
(
IN PCMiniportWaveCyclicMSVAD Miniport_,
IN ULONG Pin_,
IN BOOLEAN Capture_,
IN PKSDATAFORMAT DataFormat_
)
/*++
Routine Description:
Initializes the stream object. Allocate a DMA buffer, timer and DPC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -