📄 minwave.cpp
字号:
_DbgPrintF(DEBUGLVL_VERBOSE,("returning default format intersection") );
RtlCopyMemory(ResultantFormat, ClientDataRange, sizeof( KSDATAFORMAT ) );
*ResultantFormatLength = sizeof( KSDATAFORMAT );
}
return STATUS_SUCCESS;
}
/*****************************************************************************
* CMiniportWaveCyclicSB16::NewStream()
*****************************************************************************
* Creates a new stream. This function is called when a streaming pin is
* created.
*/
STDMETHODIMP
CMiniportWaveCyclicSB16::
NewStream
(
OUT PMINIPORTWAVECYCLICSTREAM * OutStream,
IN PUNKNOWN OuterUnknown,
IN POOL_TYPE PoolType,
IN ULONG Channel,
IN BOOLEAN Capture,
IN PKSDATAFORMAT DataFormat,
OUT PDMACHANNEL * OutDmaChannel,
OUT PSERVICEGROUP * OutServiceGroup
)
{
PAGED_CODE();
ASSERT(OutStream);
ASSERT(DataFormat);
ASSERT(OutDmaChannel);
ASSERT(OutServiceGroup);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicSB16::NewStream]"));
NTSTATUS ntStatus = STATUS_SUCCESS;
//
// Make sure the hardware is not already in use.
//
if (Capture)
{
if (AllocatedCapture)
{
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}
}
else
{
if (AllocatedRender)
{
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}
}
//
// Determine if the format is valid.
//
if (NT_SUCCESS(ntStatus))
{
ntStatus = ValidateFormat(DataFormat);
}
if(NT_SUCCESS(ntStatus))
{
// if we're trying to start a full-duplex stream.
if(AllocatedCapture || AllocatedRender)
{
// make sure the requested sampling rate is the
// same as the currently running one...
PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1);
if( SamplingFrequency != waveFormat->nSamplesPerSec )
{
// Bad format....
ntStatus = STATUS_INVALID_PARAMETER;
}
}
}
PDMACHANNELSLAVE dmaChannel = NULL;
PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1);
//
// Get the required DMA channel if it's not already in use.
//
if (NT_SUCCESS(ntStatus))
{
if (waveFormat->wBitsPerSample == 8)
{
if (! Allocated8Bit)
{
dmaChannel = DmaChannel8;
}
}
else
{
if (! Allocated16Bit)
{
dmaChannel = DmaChannel16;
}
}
}
if (! dmaChannel)
{
ntStatus = STATUS_INVALID_DEVICE_REQUEST;
}
else
{
//
// Instantiate a stream.
//
CMiniportWaveCyclicStreamSB16 *stream =
new(PoolType) CMiniportWaveCyclicStreamSB16(OuterUnknown);
if (stream)
{
stream->AddRef();
ntStatus =
stream->Init
(
this,
Channel,
Capture,
DataFormat,
dmaChannel
);
if (NT_SUCCESS(ntStatus))
{
if (Capture)
{
AllocatedCapture = TRUE;
}
else
{
AllocatedRender = TRUE;
}
if (waveFormat->wBitsPerSample == 8)
{
Allocated8Bit = TRUE;
}
else
{
Allocated16Bit = TRUE;
}
*OutStream = PMINIPORTWAVECYCLICSTREAM(stream);
stream->AddRef();
#if OVERRIDE_DMA_CHANNEL
*OutDmaChannel = PDMACHANNEL(stream);
stream->AddRef();
#else // OVERRIDE_DMA_CHANNEL
*OutDmaChannel = dmaChannel;
dmaChannel->AddRef();
#endif // OVERRIDE_DMA_CHANNEL
*OutServiceGroup = ServiceGroup;
ServiceGroup->AddRef();
//
// The stream, the DMA channel, and the service group have
// references now for the caller. The caller expects these
// references to be there.
//
}
//
// This is our private reference to the stream. The caller has
// its own, so we can release in any case.
//
stream->Release();
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
return ntStatus;
}
/*****************************************************************************
* CMiniportWaveCyclic::RestoreSampleRate()
*****************************************************************************
* Restores the sample rate.
*/
STDMETHODIMP_(void) CMiniportWaveCyclicSB16::RestoreSampleRate (void)
{
if (AllocatedCapture)
{
_DbgPrintF(DEBUGLVL_VERBOSE, ("Restoring Capture Sample Rate"));
AdapterCommon->WriteController(DSP_CMD_SETADCRATE);
AdapterCommon->WriteController((BYTE)(SamplingFrequency >> 8));
AdapterCommon->WriteController((BYTE) SamplingFrequency);
}
if (AllocatedRender)
{
_DbgPrintF(DEBUGLVL_VERBOSE, ("Restoring Render Sample Rate"));
AdapterCommon->WriteController(DSP_CMD_SETDACRATE);
AdapterCommon->WriteController((BYTE)(SamplingFrequency >> 8));
AdapterCommon->WriteController((BYTE) SamplingFrequency);
}
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::NonDelegatingQueryInterface()
*****************************************************************************
* Obtains an interface. This function works just like a COM QueryInterface
* call and is used if the object is not being aggregated.
*/
STDMETHODIMP
CMiniportWaveCyclicStreamSB16::
NonDelegatingQueryInterface
(
IN REFIID Interface,
OUT PVOID * Object
)
{
PAGED_CODE();
ASSERT(Object);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::NonDelegatingQueryInterface]"));
if (IsEqualGUIDAligned(Interface,IID_IUnknown))
{
*Object = PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this)));
}
else
if (IsEqualGUIDAligned(Interface,IID_IMiniportWaveCyclicStream))
{
*Object = PVOID(PMINIPORTWAVECYCLICSTREAM(this));
}
else
if (IsEqualGUIDAligned (Interface, IID_IDrmAudioStream))
{
*Object = (PVOID)(PDRMAUDIOSTREAM(this));
}
#if OVERRIDE_DMA_CHANNEL
else
if (IsEqualGUIDAligned (Interface, IID_IDmaChannel))
{
*Object = (PVOID)(PDMACHANNEL(this));
}
#endif // OVERRIDE_DMA_CHANNEL
else
{
*Object = NULL;
}
if (*Object)
{
PUNKNOWN(*Object)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::~CMiniportWaveCyclicStreamSB16()
*****************************************************************************
* Destructor.
*/
CMiniportWaveCyclicStreamSB16::
~CMiniportWaveCyclicStreamSB16
( void
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::~CMiniportWaveCyclicStreamSB16]"));
if (DmaChannel)
{
DmaChannel->Release();
}
if (Miniport)
{
//
// Clear allocation flags in the miniport.
//
if (Capture)
{
Miniport->AllocatedCapture = FALSE;
}
else
{
Miniport->AllocatedRender = FALSE;
}
if (Format16Bit)
{
Miniport->Allocated16Bit = FALSE;
}
else
{
Miniport->Allocated8Bit = FALSE;
}
Miniport->AdapterCommon->SaveMixerSettingsToRegistry();
Miniport->Release();
}
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::Init()
*****************************************************************************
* Initializes a stream.
*/
NTSTATUS
CMiniportWaveCyclicStreamSB16::
Init
(
IN CMiniportWaveCyclicSB16 * Miniport_,
IN ULONG Channel_,
IN BOOLEAN Capture_,
IN PKSDATAFORMAT DataFormat,
IN PDMACHANNELSLAVE DmaChannel_
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::Init]"));
ASSERT(Miniport_);
ASSERT(DataFormat);
ASSERT(NT_SUCCESS(Miniport_->ValidateFormat(DataFormat)));
ASSERT(DmaChannel_);
PWAVEFORMATEX waveFormat = PWAVEFORMATEX(DataFormat + 1);
//
// We must add references because the caller will not do it for us.
//
Miniport = Miniport_;
Miniport->AddRef();
DmaChannel = DmaChannel_;
DmaChannel->AddRef();
Channel = Channel_;
Capture = Capture_;
FormatStereo = (waveFormat->nChannels == 2);
Format16Bit = (waveFormat->wBitsPerSample == 16);
State = KSSTATE_STOP;
RestoreInputMixer = FALSE;
KeWaitForSingleObject
(
&Miniport->SampleRateSync,
Executive,
KernelMode,
FALSE,
NULL
);
Miniport->SamplingFrequency = waveFormat->nSamplesPerSec;
KeReleaseMutex(&Miniport->SampleRateSync,FALSE);
return SetFormat( DataFormat );
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::SetNotificationFreq()
*****************************************************************************
* Sets the notification frequency.
*/
STDMETHODIMP_(ULONG)
CMiniportWaveCyclicStreamSB16::
SetNotificationFreq
(
IN ULONG Interval,
OUT PULONG FramingSize
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::SetNotificationFreq]"));
Miniport->NotificationInterval = Interval;
//
// This value needs to be sample block aligned for DMA to work correctly.
//
*FramingSize =
(1 << (FormatStereo + Format16Bit)) *
(Miniport->SamplingFrequency * Interval / 1000);
return Miniport->NotificationInterval;
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::SetFormat()
*****************************************************************************
* Sets the wave format.
*/
STDMETHODIMP
CMiniportWaveCyclicStreamSB16::
SetFormat
(
IN PKSDATAFORMAT Format
)
{
PAGED_CODE();
ASSERT(Format);
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::SetFormat]"));
NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
if(State != KSSTATE_RUN)
{
ntStatus = Miniport->ValidateFormat(Format);
PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1);
KeWaitForSingleObject
(
&Miniport->SampleRateSync,
Executive,
KernelMode,
FALSE,
NULL
);
// check for full-duplex stuff
if( NT_SUCCESS(ntStatus)
&& Miniport->AllocatedCapture
&& Miniport->AllocatedRender
)
{
// no new formats.... bad...
if( Miniport->SamplingFrequency != waveFormat->nSamplesPerSec )
{
// Bad format....
ntStatus = STATUS_INVALID_PARAMETER;
}
}
// TODO: Validate sample size.
if (NT_SUCCESS(ntStatus))
{
Miniport->SamplingFrequency = waveFormat->nSamplesPerSec;
BYTE command =
( Capture
? DSP_CMD_SETADCRATE
: DSP_CMD_SETDACRATE
);
Miniport->AdapterCommon->WriteController
(
command
);
Miniport->AdapterCommon->WriteController
(
(BYTE)(waveFormat->nSamplesPerSec >> 8)
);
Miniport->AdapterCommon->WriteController
(
(BYTE) waveFormat->nSamplesPerSec
);
_DbgPrintF(DEBUGLVL_VERBOSE,(" SampleRate: %d",waveFormat->nSamplesPerSec));
}
KeReleaseMutex(&Miniport->SampleRateSync,FALSE);
}
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -