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 + -
显示快捷键?