⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minwave.cpp

📁 winddk src目录下的WDM源码压缩!
💻 CPP
📖 第 1 页 / 共 4 页
字号:

/*****************************************************************************
 * 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 + -