minwave.cpp

来自「winddk src目录下的WDM源码压缩!」· C++ 代码 · 共 1,666 行 · 第 1/5 页

CPP
1,666
字号
                                          MaximumDmaSpeed,  // DmaSpeed
                                          0x1FFFE,          // MaximumLength (128KByte -2)
                                          0);               // DmaPort
    if (!NT_SUCCESS (ntStatus))
    {
        DOUT (DBG_ERROR, ("Failed on NewMasterDmaChannel!"));
        return ntStatus;
    }

    //
    // Get the DMA adapter.
    //
    AdapterObject = DmaChannel->GetAdapterObject ();

    //
    // On failure object is destroyed which cleans up.
    //
    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CAdapterCommon::BuildDataRangeInformation
 *****************************************************************************
 * This function dynamically build the data range information for the pins.
 * It also connects the static arrays with the data range information
 * structure.
 * If this function returns with an error the miniport should be destroyed.
 *
 * To build the data range information, we test the most popular sample rates,
 * the functions calls ProgramSampleRate in AdapterCommon object to actually
 * program the sample rate. After probing that way for multiple sample rates,
 * the original value, which is 48KHz is, gets restored.
 * We have to test the sample rates for playback, capture and microphone
 * separately. Every time we succeed, we update the data range information and
 * the pointers that point to it.
 */
NTSTATUS CMiniportWaveICH::BuildDataRangeInformation (void)
{
    PAGED_CODE ();

    NTSTATUS    ntStatus;
    int nWavePlaybackEntries = 0;
    int nWaveRecordingEntries = 0;
    int nMicEntries = 0;
    int nChannels;
    int nLoop;

    DOUT (DBG_PRINT, ("[CMiniportWaveICH::BuildDataRangeInformation]"));

    //
    // Calculate the number of max. channels available in the codec.
    //
    if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
    {
        if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
        {
            nChannels = 6;
        }
        else
        {
            nChannels = 4;
        }
    }
    else
    {
        nChannels = 2;
    }

    // Check for the render sample rates.
    for (nLoop = 0; nLoop < WAVE_SAMPLERATES_TESTED; nLoop++)
    {
        ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_FRONT_SAMPLERATE,
                                                     dwWaveSampleRates[nLoop]);

        // We support the sample rate?
        if (NT_SUCCESS (ntStatus))
        {
            // Add it to the PinDataRange
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Flags      = 0;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.SampleSize = nChannels * 2;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Reserved   = 0;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.SubFormat   = KSDATAFORMAT_SUBTYPE_PCM;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].DataRange.Specifier   = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumChannels = nChannels;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].MinimumBitsPerSample = 16;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumBitsPerSample = 16;
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].MinimumSampleFrequency = dwWaveSampleRates[nLoop];
            PinDataRangesPCMStreamRender[nWavePlaybackEntries].MaximumSampleFrequency = dwWaveSampleRates[nLoop];

            // Add it to the PinDataRangePointer
            PinDataRangePointersPCMStreamRender[nWavePlaybackEntries] = (PKSDATARANGE)&PinDataRangesPCMStreamRender[nWavePlaybackEntries];

            // Increase count
            nWavePlaybackEntries++;
        }
    }

    // Check for the capture sample rates.
    for (nLoop = 0; nLoop < WAVE_SAMPLERATES_TESTED; nLoop++)
    {
        ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_RECORD_SAMPLERATE, dwWaveSampleRates[nLoop]);

        // We support the sample rate?
        if (NT_SUCCESS (ntStatus))
        {
            // Add it to the PinDataRange
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Flags      = 0;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.SampleSize = 4;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Reserved   = 0;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.SubFormat   = KSDATAFORMAT_SUBTYPE_PCM;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].DataRange.Specifier   = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumChannels = 2;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MinimumBitsPerSample = 16;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumBitsPerSample = 16;
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MinimumSampleFrequency = dwWaveSampleRates[nLoop];
            PinDataRangesPCMStreamCapture[nWaveRecordingEntries].MaximumSampleFrequency = dwWaveSampleRates[nLoop];

            // Add it to the PinDataRangePointer
            PinDataRangePointersPCMStreamCapture[nWaveRecordingEntries] = (PKSDATARANGE)&PinDataRangesPCMStreamCapture[nWaveRecordingEntries];

            // Increase count
            nWaveRecordingEntries++;
        }
    }

    // Check for the MIC sample rates.
    for (nLoop = 0; nLoop < MIC_SAMPLERATES_TESTED; nLoop++)
    {
        ntStatus = AdapterCommon->ProgramSampleRate (AC97REG_MIC_SAMPLERATE, dwMicSampleRates[nLoop]);

        // We support the sample rate?
        if (NT_SUCCESS (ntStatus))
        {
            // Add it to the PinDataRange
            PinDataRangesMicStream[nMicEntries].DataRange.FormatSize = sizeof(KSDATARANGE_AUDIO);
            PinDataRangesMicStream[nMicEntries].DataRange.Flags      = 0;
            PinDataRangesMicStream[nMicEntries].DataRange.SampleSize = 2;
            PinDataRangesMicStream[nMicEntries].DataRange.Reserved   = 0;
            PinDataRangesMicStream[nMicEntries].DataRange.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
            PinDataRangesMicStream[nMicEntries].DataRange.SubFormat   = KSDATAFORMAT_SUBTYPE_PCM;
            PinDataRangesMicStream[nMicEntries].DataRange.Specifier   = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
            PinDataRangesMicStream[nMicEntries].MaximumChannels = 1;
            PinDataRangesMicStream[nMicEntries].MinimumBitsPerSample = 16;
            PinDataRangesMicStream[nMicEntries].MaximumBitsPerSample = 16;
            PinDataRangesMicStream[nMicEntries].MinimumSampleFrequency = dwMicSampleRates[nLoop];
            PinDataRangesMicStream[nMicEntries].MaximumSampleFrequency = dwMicSampleRates[nLoop];

            // Add it to the PinDataRangePointer
            PinDataRangePointersMicStream[nMicEntries] = (PKSDATARANGE)&PinDataRangesMicStream[nMicEntries];

            // Increase count
            nMicEntries++;
        }
    }

    // Now go through the pin descriptor list and change the data range entries to the actual number.
    for (nLoop = 0; nLoop < SIZEOF_ARRAY(MiniportPins); nLoop++)
    {
        if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersPCMStreamRender)
            MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nWavePlaybackEntries;
        if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersPCMStreamCapture)
            MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nWaveRecordingEntries;
        if (MiniportPins[nLoop].KsPinDescriptor.DataRanges == PinDataRangePointersMicStream)
            MiniportPins[nLoop].KsPinDescriptor.DataRangesCount = nMicEntries;
    }

    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CMiniportWaveICH::NewStream
 *****************************************************************************
 * Creates a new stream.
 * This function is called when a streaming pin is created.
 * It checks if the channel is already in use, tests the data format, creates
 * and initializes the stream object.
 */
STDMETHODIMP CMiniportWaveICH::NewStream
(
    OUT PMINIPORTWAVEPCISTREAM *Stream,
    IN  PUNKNOWN                OuterUnknown,
    IN  POOL_TYPE               PoolType,
    IN  PPORTWAVEPCISTREAM      PortStream,
    IN  ULONG                   Channel_,
    IN  BOOLEAN                 Capture,
    IN  PKSDATAFORMAT           DataFormat,
    OUT PDMACHANNEL            *DmaChannel_,
    OUT PSERVICEGROUP          *ServiceGroup
)
{
    PAGED_CODE ();

    ASSERT (Stream);
    ASSERT (PortStream);
    ASSERT (DataFormat);
    ASSERT (DmaChannel_);
    ASSERT (ServiceGroup);

    CMiniportWaveICHStream *pWaveICHStream = NULL;
    NTSTATUS ntStatus = STATUS_SUCCESS;

    DOUT (DBG_PRINT, ("[CMiniportWaveICH::NewStream]"));

    //
    // Validate the channel (pin id).
    //
    if ((Channel_ != PIN_WAVEOUT) && (Channel_ != PIN_WAVEIN) &&
       (Channel_ != PIN_MICIN))
    {
        DOUT (DBG_ERROR, ("[NewStream] Invalid channel passed!"));
        return STATUS_INVALID_PARAMETER;
    }

    //
    // Check if the pin is already in use
    //
    ULONG Channel = Channel_ >> 1;
    if (Streams[Channel])
    {
        DOUT (DBG_ERROR, ("[NewStream] Pin is already in use!"));
        return STATUS_UNSUCCESSFUL;
    }

    //
    // Check parameters.
    //
    ntStatus = TestDataFormat (DataFormat, (WavePins)Channel_);
    if (!NT_SUCCESS (ntStatus))
    {
        DOUT (DBG_VSR, ("[NewStream] TestDataFormat failed!"));
        return ntStatus;
    }
        
    //
    // Create a new stream.
    //
    ntStatus = CreateMiniportWaveICHStream (&pWaveICHStream, OuterUnknown,
                                            PoolType);

    //
    // Return in case of an error.
    //
    if (!NT_SUCCESS (ntStatus))
    {
        DOUT (DBG_ERROR, ("[NewStream] Failed to create stream!"));
        return ntStatus;
    }

    //
    // Initialize the stream.
    //
    ntStatus = pWaveICHStream->Init (this,
                                    PortStream,
                                    Channel,
                                    Capture,
                                    DataFormat,
                                    ServiceGroup);
    if (!NT_SUCCESS (ntStatus))
    {
        //
        // Release the stream and clean up.
        //
        DOUT (DBG_ERROR, ("[NewStream] Failed to init stream!"));
        pWaveICHStream->Release ();
        // In case the stream passed us a ServiceGroup, portcls will ignore all parameters
        // on a failure, so we have to release it here.
        if (*ServiceGroup)
            (*ServiceGroup)->Release();
        *ServiceGroup = NULL;
        *Stream = NULL;
        *DmaChannel_ = NULL;
        return ntStatus;
    }

    // 
    // Save the pointers.
    //
    *Stream = (PMINIPORTWAVEPCISTREAM)pWaveICHStream;
    *DmaChannel_ = DmaChannel;
    
    
    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CMiniportWaveICH::GetDescription
 *****************************************************************************
 * Gets the topology.
 */
STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::GetDescription
(
    OUT PPCFILTER_DESCRIPTOR *OutFilterDescriptor
)
{
    PAGED_CODE ();

    ASSERT (OutFilterDescriptor);

    DOUT (DBG_PRINT, ("[CMiniportWaveICH::GetDescription]"));

    *OutFilterDescriptor = &MiniportFilterDescriptor;


    return STATUS_SUCCESS;
}


/*****************************************************************************
 * CMiniportWaveICH::DataRangeIntersection
 *****************************************************************************
 * Tests a data range intersection.
 * Cause the AC97 controller does not support mono render or capture, we have
 * to check the max. channel field (unfortunately, there is no MinimumChannel
 * and MaximumChannel field, just a MaximumChannel field).
 * If the MaximumChannel is 2, then we can pass this to the default handler of
 * portcls which always chooses the most (SampleFrequency, Channel, Bits etc.)
 *
 * This DataRangeIntersection function is strictly only for the exposed formats
 * in this sample driver. If you intend to add other formats like AC3 then
 * you have to be make sure that you check the GUIDs and the data range, since
 * portcls only checks the data range for waveformatex.
 */
STDMETHODIMP_(NTSTATUS) CMiniportWaveICH::DataRangeIntersection
(
    IN      ULONG           PinId,
    IN      PKSDATARANGE    ClientsDataRange,
    IN      PKSDATARANGE    MyDataRange,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?