Exemple #1
0
//=============================================================================
STDMETHODIMP_(NTSTATUS) CMiniportWaveCyclicStream::SetFormat(
    IN  PKSDATAFORMAT           Format
)
/*++
Routine Description:
  The SetFormat function changes the format associated with a stream.
  Callers of SetFormat should run at IRQL PASSIVE_LEVEL

Arguments:
  Format - Pointer to a KSDATAFORMAT structure which indicates the new format
           of the stream.

Return Value:
  NT status code.
--*/
{
    PAGED_CODE();

    ASSERT(Format);

    DPF_ENTER(("[CMiniportWaveCyclicStream::SetFormat]"));

    NTSTATUS      ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    PWAVEFORMATEX pWfx;

    if (m_ksState != KSSTATE_RUN) {
        // MSVAD does not validate the format.
        pWfx = GetWaveFormatEx(Format);
        if (pWfx) {
            ntStatus = KeWaitForSingleObject(&m_pMiniport->m_SampleRateSync, Executive, KernelMode, FALSE, NULL);
            if (STATUS_SUCCESS == ntStatus) {
                m_usBlockAlign = pWfx->nBlockAlign;
                m_fFormat16Bit = (pWfx->wBitsPerSample == 16);
                m_pMiniport->m_SamplingFrequency = pWfx->nSamplesPerSec;
                m_ulDmaMovementRate = pWfx->nAvgBytesPerSec;

                DPF(D_TERSE, ("New Format - SpS: %d - BpS: %d - aBypS: %d - C: %d", pWfx->nSamplesPerSec, pWfx->wBitsPerSample, pWfx->nAvgBytesPerSec, pWfx->nChannels));
            }

            KeReleaseMutex(&m_pMiniport->m_SampleRateSync, FALSE);
        }
    }

    return ntStatus;
} // SetFormat
Exemple #2
0
NTSTATUS
CMiniportWaveRTStream::Init
( 
    _In_ PCMiniportWaveRT           Miniport_,
    _In_ PPORTWAVERTSTREAM          PortStream_,
    _In_ ULONG                      Pin_,
    _In_ BOOLEAN                    Capture_,
    _In_ PKSDATAFORMAT              DataFormat_,
    _In_ GUID                       SignalProcessingMode
)
/*++

Routine Description:

  Initializes the stream object.

Arguments:

  Miniport_ -

  Pin_ -

  Capture_ -

  DataFormat -

  SignalProcessingMode - The driver uses the signalProcessingMode to configure
    driver and/or hardware specific signal processing to be applied to this new
    stream.

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    PWAVEFORMATEX pWfEx = NULL;
    NTSTATUS ntStatus = STATUS_SUCCESS;

    m_pMiniport = NULL;
    m_ulPin = 0;
    m_bUnregisterStream = FALSE;
    m_bCapture = FALSE;
    m_ulDmaBufferSize = 0;
    m_pDmaBuffer = NULL;
    m_KsState = KSSTATE_STOP;
    m_pTimer = NULL;
    m_pDpc = NULL;
    m_ullPlayPosition = 0;
    m_ullWritePosition = 0;
    m_ullDmaTimeStamp = 0;
    m_hnsElapsedTimeCarryForward = 0;
    m_ulDmaMovementRate = 0;
    m_bLfxEnabled = FALSE;
    m_pbMuted = NULL;
    m_plVolumeLevel = NULL;
    m_plPeakMeter = NULL;
    m_pWfExt = NULL;
    m_ullLinearPosition = 0;
    m_ulContentId = 0;
    m_ulCurrentWritePosition = 0;
    m_IsCurrentWritePositionUpdated = 0;
    
#ifdef SYSVAD_BTH_BYPASS
    m_ScoOpen = FALSE;
#endif  // SYSVAD_BTH_BYPASS

    m_pPortStream = PortStream_;
    InitializeListHead(&m_NotificationList);
    m_ulNotificationIntervalMs = 0;

    m_pNotificationDpc = (PRKDPC)ExAllocatePoolWithTag(
        NonPagedPoolNx,
        sizeof(KDPC),
        MINWAVERTSTREAM_POOLTAG);
    if (!m_pNotificationDpc)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    m_pNotificationTimer = (PKTIMER)ExAllocatePoolWithTag(
        NonPagedPoolNx,
        sizeof(KTIMER),
        MINWAVERTSTREAM_POOLTAG);
    if (!m_pNotificationTimer)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    KeInitializeDpc(m_pNotificationDpc, TimerNotifyRT, this);
    KeInitializeTimerEx(m_pNotificationTimer, NotificationTimer);

    pWfEx = GetWaveFormatEx(DataFormat_);
    if (NULL == pWfEx) 
    { 
        return STATUS_UNSUCCESSFUL; 
    }

    m_pMiniport = reinterpret_cast<CMiniportWaveRT*>(Miniport_);
    if (m_pMiniport == NULL)
    {
        return STATUS_INVALID_PARAMETER;
    }
    m_pMiniport->AddRef();
    if (!NT_SUCCESS(ntStatus))
    {
        return ntStatus;
    }
    m_ulPin = Pin_;
    m_bCapture = Capture_;
    m_ulDmaMovementRate = pWfEx->nAvgBytesPerSec;

    m_pDpc = (PRKDPC)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(KDPC), MINWAVERTSTREAM_POOLTAG);
    if (!m_pDpc)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    m_pWfExt = (PWAVEFORMATEXTENSIBLE)ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(WAVEFORMATEX) + pWfEx->cbSize, MINWAVERTSTREAM_POOLTAG);
    if (m_pWfExt == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlCopyMemory(m_pWfExt, pWfEx, sizeof(WAVEFORMATEX) + pWfEx->cbSize);

    m_pbMuted = (PBOOL)ExAllocatePoolWithTag(NonPagedPoolNx, m_pWfExt->Format.nChannels * sizeof(BOOL), MINWAVERTSTREAM_POOLTAG);
    if (m_pbMuted == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(m_pbMuted, m_pWfExt->Format.nChannels * sizeof(BOOL));

    m_plVolumeLevel = (PLONG)ExAllocatePoolWithTag(NonPagedPoolNx, m_pWfExt->Format.nChannels * sizeof(LONG), MINWAVERTSTREAM_POOLTAG);
    if (m_plVolumeLevel == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(m_plVolumeLevel, m_pWfExt->Format.nChannels * sizeof(LONG));

    m_plPeakMeter = (PLONG)ExAllocatePoolWithTag(NonPagedPoolNx, m_pWfExt->Format.nChannels * sizeof(LONG), MINWAVERTSTREAM_POOLTAG);
    if (m_plPeakMeter == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory(m_plPeakMeter, m_pWfExt->Format.nChannels * sizeof(LONG));

    if (m_bCapture)
    {
        DWORD toneFrequency = 0;

        if (!m_pMiniport->IsRenderDevice())
        {
            //
            // Init sine wave generator. To exercise the SignalProcessingMode parameter
            // this sample driver selects the frequency based on the parameter.
            //
            toneFrequency = IsEqualGUID(SignalProcessingMode, AUDIO_SIGNALPROCESSINGMODE_RAW) ? 1000 : 2000;
        }
        else 
        {
            //
            // Loopbacks pins use a different frequency for test validation.
            //
            ASSERT(Pin_ == m_pMiniport->GetLoopbackPinId());
            toneFrequency = 3000; // 3 kHz
        }
        
        ntStatus = m_ToneGenerator.Init(toneFrequency, m_pWfExt);
        if (!NT_SUCCESS(ntStatus))
        {
            return ntStatus;
        }
    }
    else if (!g_DoNotCreateDataFiles)
    {
        //
        // Create an output file for the render data.
        //
        DPF(D_TERSE, ("SaveData %p", &m_SaveData));
        ntStatus = m_SaveData.SetDataFormat(DataFormat_);
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = m_SaveData.Initialize(m_pMiniport->IsOffloadSupported() ? (Pin_ == m_pMiniport->GetOffloadPinId()) : FALSE);
        }
    
        if (!NT_SUCCESS(ntStatus))
        {
            return ntStatus;
        }
    }

    //
    // Register this stream.
    //
    ntStatus = m_pMiniport->StreamCreated(m_ulPin, this);
    if (NT_SUCCESS(ntStatus))
    {
        m_bUnregisterStream = TRUE;
    }

    return ntStatus;
} // Init
Exemple #3
0
//=============================================================================
NTSTATUS                    
CMiniportWaveCyclic::ValidateFormat
(
    IN  ULONG               nPin,
    IN  PKSDATAFORMAT       pDataFormat 
)
/*++

Routine Description:

  Validates that the given dataformat is valid. This overwrites BaseWave's
  ValidateFormat and includes checks for AC3 format.

Arguments:

  pDataFormat - The dataformat for validation.

Return Value:

  NT status code.

--*/
{
    PAGED_CODE();

    DPF_ENTER(("[CMiniportWaveCyclic::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);

            if ((wfxID == WAVE_FORMAT_PCM) ||
                ((wfxID == WAVE_FORMAT_DOLBY_AC3_SPDIF) &&
                ((nPin == KSPIN_WAVE_SPDIF_CAPTURE_HOST) || (nPin == KSPIN_WAVE_SPDIF_RENDER_HOST))))
            {
                if
                (
                    (pDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)) &&
                    (pwfx->cbSize == 0)                              &&
                    (pwfx->nChannels <= MAX_CHANNELS )           &&
                    (pwfx->wBitsPerSample >= MIN_BITS_PER_SAMPLE)&&
                    (pwfx->wBitsPerSample <= MAX_BITS_PER_SAMPLE)&&
                    (pwfx->nSamplesPerSec >= MIN_SAMPLE_RATE)    &&
                    (pwfx->nSamplesPerSec <= MAX_SAMPLE_RATE)
                )
                {
                    ntStatus = STATUS_SUCCESS;
                }
                else
                {
                    DPF(D_TERSE, ("Invalid format"));
                }
            }
            else
            {
                DPF(D_TERSE, ("Invalid format tag"));
            }
        }
        else
        {
            DPF(D_TERSE, ("Invalid pDataFormat->SubFormat!") );
        }
    }

    return ntStatus;
} // ValidateFormat
Exemple #4
0
//=============================================================================
NTSTATUS CMiniportWaveCyclicStream::Init( 
    IN PCMiniportWaveCyclic         Miniport_,
    IN ULONG                        Pin_,
    IN BOOLEAN                      Capture_,
    IN PKSDATAFORMAT                DataFormat_
)
/*++
Routine Description:
  Initializes the stream object. Allocate a DMA buffer, timer and DPC

Arguments:
  Miniport_ -
  Pin_ -
  Capture_ -
  DataFormat -
  DmaChannel_ -

Return Value:
  NT status code.
--*/
{
    PAGED_CODE();

    ASSERT(Miniport_);
    ASSERT(DataFormat_);


    NTSTATUS      ntStatus = STATUS_SUCCESS;
    PWAVEFORMATEX pWfx;

    pWfx = GetWaveFormatEx(DataFormat_);
    if (!pWfx) {
        DPF(D_TERSE, ("Invalid DataFormat param in NewStream"));
        ntStatus = STATUS_INVALID_PARAMETER;
    }

    if (NT_SUCCESS(ntStatus)) {
        m_pMiniport                       = Miniport_;

        m_ulPin                           = Pin_;
        m_fCapture                        = Capture_;
        m_usBlockAlign                    = pWfx->nBlockAlign;
        m_fFormat16Bit                    = (pWfx->wBitsPerSample == 16);
        m_ksState                         = KSSTATE_STOP;
        m_ulDmaPosition                   = 0;
        m_ullElapsedTimeCarryForward      = 0;
        m_ulByteDisplacementCarryForward  = 0;
        m_fDmaActive                      = FALSE;
        m_pDpc                            = NULL;
        m_pTimer                          = NULL;
        m_pvDmaBuffer                     = NULL;

        // If this is not the capture stream, create the output file.
        if (!m_fCapture) {
            if (NT_SUCCESS(ntStatus)) {
                ntStatus = m_SaveData.Initialize();
            }
        }
    }

    // Allocate DMA buffer for this stream.
    if (NT_SUCCESS(ntStatus)) {
        ntStatus = AllocateBuffer(m_pMiniport->m_MaxDmaBufferSize, NULL);
    }

    // Set sample frequency. Note that m_SampleRateSync access should
    // be syncronized.
    if (NT_SUCCESS(ntStatus)) {
        ntStatus = KeWaitForSingleObject(&m_pMiniport->m_SampleRateSync, Executive, KernelMode, FALSE, NULL);
        if (STATUS_SUCCESS == ntStatus) {
            m_pMiniport->m_SamplingFrequency = pWfx->nSamplesPerSec;
            KeReleaseMutex(&m_pMiniport->m_SampleRateSync, FALSE);
        } else {
            DPF(D_TERSE, ("[SamplingFrequency Sync failed: %08X]", ntStatus));
        }
    }

    if (NT_SUCCESS(ntStatus)) {
        ntStatus = SetFormat(DataFormat_);
    }

    if (NT_SUCCESS(ntStatus)) {
        m_pDpc = (PRKDPC) ExAllocatePoolWithTag(NonPagedPool, sizeof(KDPC), MSVAD_POOLTAG);
        if (!m_pDpc) {
            DPF(D_TERSE, ("[Could not allocate memory for DPC]"));
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    if (NT_SUCCESS(ntStatus)) {
        m_pTimer = (PKTIMER) ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), MSVAD_POOLTAG);
        if (!m_pTimer) {
            DPF(D_TERSE, ("[Could not allocate memory for Timer]"));
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        }
    }

    if (NT_SUCCESS(ntStatus)) {
        KeInitializeDpc(m_pDpc, TimerNotify, m_pMiniport);
        KeInitializeTimerEx(m_pTimer, NotificationTimer);
    }

    return ntStatus;
} // Init