📄 minwave.cpp
字号:
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::SetState()
*****************************************************************************
* Sets the state of the channel.
*/
STDMETHODIMP
CMiniportWaveCyclicStreamSB16::
SetState
(
IN KSSTATE NewState
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::SetState %x]", NewState));
NTSTATUS ntStatus = STATUS_SUCCESS;
//
// The acquire state is not distinguishable from the pause state for our
// purposes.
//
if (NewState == KSSTATE_ACQUIRE)
{
NewState = KSSTATE_PAUSE;
}
if (State != NewState)
{
switch (NewState)
{
case KSSTATE_PAUSE:
if (State == KSSTATE_RUN)
{
if (Capture)
{
// restore if previously setup for mono recording
// (this should really be done via the topology miniport)
if(RestoreInputMixer)
{
Miniport->AdapterCommon->MixerRegWrite( DSP_MIX_ADCMIXIDX_L,
InputMixerLeft );
RestoreInputMixer = FALSE;
}
}
// TODO: Wait for DMA to complete
if (Format16Bit)
{
Miniport->AdapterCommon->WriteController(DSP_CMD_HALTAUTODMA16);
// TODO: wait...
Miniport->AdapterCommon->WriteController(DSP_CMD_PAUSEDMA16);
}
else
{
Miniport->AdapterCommon->WriteController(DSP_CMD_HALTAUTODMA);
// TODO: wait...
Miniport->AdapterCommon->WriteController(DSP_CMD_PAUSEDMA);
}
Miniport->AdapterCommon->WriteController(DSP_CMD_SPKROFF);
DmaChannel->Stop();
}
break;
case KSSTATE_RUN:
{
BYTE mode;
if (Capture)
{
// setup for mono recording
// (this should really be done via the topology miniport)
if(! FormatStereo)
{
InputMixerLeft = Miniport->AdapterCommon->MixerRegRead( DSP_MIX_ADCMIXIDX_L );
UCHAR InputMixerRight = Miniport->AdapterCommon->MixerRegRead( DSP_MIX_ADCMIXIDX_R );
UCHAR TempMixerValue = InputMixerLeft | (InputMixerRight & 0x2A);
Miniport->AdapterCommon->MixerRegWrite( DSP_MIX_ADCMIXIDX_L,
TempMixerValue );
RestoreInputMixer = TRUE;
}
//
// Turn on capture.
//
Miniport->AdapterCommon->WriteController(DSP_CMD_SPKROFF);
if (Format16Bit)
{
Miniport->AdapterCommon->WriteController(DSP_CMD_STARTADC16);
mode = 0x10;
}
else
{
Miniport->AdapterCommon->WriteController(DSP_CMD_STARTADC8);
mode = 0x00;
}
}
else
{
Miniport->AdapterCommon->WriteController(DSP_CMD_SPKRON);
if (Format16Bit)
{
Miniport->AdapterCommon->WriteController(DSP_CMD_STARTDAC16);
mode = 0x10;
}
else
{
Miniport->AdapterCommon->WriteController(DSP_CMD_STARTDAC8);
mode = 0x00;
}
}
if (FormatStereo)
{
mode |= 0x20;
}
//
// Start DMA.
//
DmaChannel->Start(DmaChannel->BufferSize(),!Capture);
Miniport->AdapterCommon->WriteController(mode) ;
//
// Calculate sample count for interrupts.
//
ULONG bufferSizeInFrames = DmaChannel->BufferSize();
if( Format16Bit )
{
bufferSizeInFrames /= 2;
}
if( FormatStereo )
{
bufferSizeInFrames /= 2;
}
ULONG frameCount =
((Miniport->SamplingFrequency * Miniport->NotificationInterval) / 1000);
if (frameCount > bufferSizeInFrames)
{
frameCount = bufferSizeInFrames;
}
frameCount--;
_DbgPrintF( DEBUGLVL_VERBOSE, ("Run. Setting frame count to %X",frameCount));
Miniport->AdapterCommon->WriteController((BYTE) frameCount) ;
Miniport->AdapterCommon->WriteController((BYTE) (frameCount >> 8));
}
break;
case KSSTATE_STOP:
break;
}
State = NewState;
}
return ntStatus;
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::SetContentId
*****************************************************************************
* This routine gets called by drmk.sys to pass the content to the driver.
* The driver has to enforce the rights passed.
*/
STDMETHODIMP_(NTSTATUS)
CMiniportWaveCyclicStreamSB16::SetContentId
(
IN ULONG contentId,
IN PCDRMRIGHTS drmRights
)
{
PAGED_CODE ();
_DbgPrintF(DEBUGLVL_VERBOSE,("[CMiniportWaveCyclicStreamSB16::SetContentId]"));
//
// if (drmRights.CopyProtect==TRUE)
// Mute waveout capture.
// Sb16 does not have waveout capture path. Therefore
// the sample driver is not using this attribute.
// Also if the driver is writing data to other types of media (disk, etc), it
// should stop doing it.
// (MSVAD\simple stops writing to disk).
// (AC97 disables waveout capture)
//
// if (drmRights.DigitalOutputDisable == TRUE)
// Mute S/PDIF out.
// If the device cannot mute S/PDIF out properly, it should return an error
// code.
// Sb16 does not have S/PDIF out. Therefore the sample driver is not using
// this attribute.
//
//
// To learn more about enforcing rights, please look at AC97 sample.
//
// To learn more about managing multiple streams, please look at MSVAD.
//
return STATUS_SUCCESS;
}
#pragma code_seg()
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::GetPosition()
*****************************************************************************
* Gets the current position. May be called at dispatch level.
*/
STDMETHODIMP
CMiniportWaveCyclicStreamSB16::
GetPosition
(
OUT PULONG Position
)
{
ASSERT(Position);
ULONG transferCount = DmaChannel->TransferCount();
if (DmaChannel && transferCount)
{
*Position = DmaChannel->ReadCounter();
ASSERT(*Position <= transferCount);
if (*Position != 0)
{
*Position = transferCount - *Position;
}
}
else
{
*Position = 0;
}
return STATUS_SUCCESS;
}
STDMETHODIMP
CMiniportWaveCyclicStreamSB16::NormalizePhysicalPosition(
IN OUT PLONGLONG PhysicalPosition
)
/*++
Routine Description:
Given a physical position based on the actual number of bytes transferred,
this function converts the position to a time-based value of 100ns units.
Arguments:
IN OUT PLONGLONG PhysicalPosition -
value to convert.
Return:
STATUS_SUCCESS or an appropriate error code.
--*/
{
*PhysicalPosition =
(_100NS_UNITS_PER_SECOND /
(1 << (FormatStereo + Format16Bit)) * *PhysicalPosition) /
Miniport->SamplingFrequency;
return STATUS_SUCCESS;
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::Silence()
*****************************************************************************
* Fills a buffer with silence.
*/
STDMETHODIMP_(void)
CMiniportWaveCyclicStreamSB16::
Silence
(
IN PVOID Buffer,
IN ULONG ByteCount
)
{
RtlFillMemory(Buffer,ByteCount,Format16Bit ? 0 : 0x80);
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::ServiceWaveISR()
*****************************************************************************
* Service the ISR - notify the port.
*/
STDMETHODIMP_(void) CMiniportWaveCyclicSB16::ServiceWaveISR (void)
{
if (Port && ServiceGroup)
{
Port->Notify (ServiceGroup);
}
}
#if OVERRIDE_DMA_CHANNEL
#pragma code_seg("PAGE")
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::AllocateBuffer()
*****************************************************************************
* Allocate a buffer for this DMA channel.
*/
STDMETHODIMP
CMiniportWaveCyclicStreamSB16::AllocateBuffer
(
IN ULONG BufferSize,
IN PPHYSICAL_ADDRESS PhysicalAddressConstraint OPTIONAL
)
{
PAGED_CODE();
return DmaChannel->AllocateBuffer(BufferSize,PhysicalAddressConstraint);
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::FreeBuffer()
*****************************************************************************
* Free the buffer for this DMA channel.
*/
STDMETHODIMP_(void)
CMiniportWaveCyclicStreamSB16::FreeBuffer(void)
{
PAGED_CODE();
DmaChannel->FreeBuffer();
}
#pragma code_seg()
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::TransferCount()
*****************************************************************************
* Return the amount of data to be transfered via DMA.
*/
STDMETHODIMP_(ULONG)
CMiniportWaveCyclicStreamSB16::TransferCount(void)
{
return DmaChannel->TransferCount();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::MaximumBufferSize()
*****************************************************************************
* Return the maximum size that can be allocated to this DMA buffer.
*/
STDMETHODIMP_(ULONG)
CMiniportWaveCyclicStreamSB16::MaximumBufferSize(void)
{
return DmaChannel->MaximumBufferSize();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::AllocatedBufferSize()
*****************************************************************************
* Return the original size allocated to this DMA buffer -- the maximum value
* that can be sent to SetBufferSize().
*/
STDMETHODIMP_(ULONG)
CMiniportWaveCyclicStreamSB16::AllocatedBufferSize(void)
{
return DmaChannel->AllocatedBufferSize();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::BufferSize()
*****************************************************************************
* Return the current size of the DMA buffer.
*/
STDMETHODIMP_(ULONG)
CMiniportWaveCyclicStreamSB16::BufferSize(void)
{
return DmaChannel->BufferSize();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::SetBufferSize()
*****************************************************************************
* Change the size of the DMA buffer. This cannot exceed the initial
* buffer size returned by AllocatedBufferSize().
*/
STDMETHODIMP_(void)
CMiniportWaveCyclicStreamSB16::SetBufferSize(IN ULONG BufferSize)
{
DmaChannel->SetBufferSize(BufferSize);
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::SystemAddress()
*****************************************************************************
* Return the virtual address of this DMA buffer.
*/
STDMETHODIMP_(PVOID)
CMiniportWaveCyclicStreamSB16::SystemAddress(void)
{
return DmaChannel->SystemAddress();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::PhysicalAddress()
*****************************************************************************
* Return the actual physical address of this DMA buffer.
*/
STDMETHODIMP_(PHYSICAL_ADDRESS)
CMiniportWaveCyclicStreamSB16::PhysicalAddress(void)
{
return DmaChannel->PhysicalAddress();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::GetAdapterObject()
*****************************************************************************
* Return the DMA adapter object (defined in wdm.h).
*/
STDMETHODIMP_(PADAPTER_OBJECT)
CMiniportWaveCyclicStreamSB16::GetAdapterObject(void)
{
return DmaChannel->GetAdapterObject();
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::CopyTo()
*****************************************************************************
* Copy data into the DMA buffer. If you need to modify data on render
* (playback), modify this routine to taste.
*/
STDMETHODIMP_(void)
CMiniportWaveCyclicStreamSB16::CopyTo
(
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount
)
{
DmaChannel->CopyTo(Destination, Source, ByteCount);
}
/*****************************************************************************
* CMiniportWaveCyclicStreamSB16::CopyFrom()
*****************************************************************************
* Copy data out of the DMA buffer. If you need to modify data on capture
* (recording), modify this routine to taste.
*/
STDMETHODIMP_(void)
CMiniportWaveCyclicStreamSB16::CopyFrom
(
IN PVOID Destination,
IN PVOID Source,
IN ULONG ByteCount
)
{
DmaChannel->CopyFrom(Destination, Source, ByteCount);
}
#endif // OVERRIDE_DMA_CHANNEL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -