📄 minwave.cpp
字号:
Port->AddRef();
#else
DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p, %p)", this, Miniport_, streamIndex_, isCaptureStream_, DataFormat, DMAChannel_, OutServiceGroup));
DMAChannel = DMAChannel_;
DMAChannel->AddRef();
#endif
Miniport = Miniport_;
Miniport->AddRef();
streamIndex = streamIndex_;
isCaptureStream = isCaptureStream_;
state = KSSTATE_STOP;
if ( (streamIndex == PCM_OUT_STREAM) || (streamIndex == AC3_OUT_STREAM) ) {
channelNumber = OUT_CHANNEL;
} else {
channelNumber = IN_CHANNEL;
}
#ifndef WAVERT
ntStatus = PcNewServiceGroup(&ServiceGroup,NULL);
if (!NT_SUCCESS(ntStatus)) {
DBGPRINT(("PcNewServiceGroup() or NewMasterDmaChannel() failed"));
return ntStatus;
}
*OutServiceGroup = ServiceGroup;
ServiceGroup->AddRef();
#endif
ntStatus = SetFormat(DataFormat);
if (!NT_SUCCESS(ntStatus)) {
DBGPRINT(("SetFormat() failed"));
return ntStatus;
}
Miniport->isStreamRunning[streamIndex] = true;
return ntStatus;
}
NTSTATUS CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format)
{
PAGED_CODE();
DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format));
PWAVEFORMATEX waveFormat = PWAVEFORMATEX(Format + 1);
NTSTATUS ntStatus = Miniport->validateFormat(Format, -1, isCaptureStream);
if (!NT_SUCCESS(ntStatus)) {
return ntStatus;
}
// the DAC and ADC can only run at the same sample rate simultaneously
if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[PCM_OUT_STREAM]) {
if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_OUT_STREAM]->currentSampleRate) {
return STATUS_UNSUCCESSFUL;
}
}
if ((streamIndex == PCM_IN_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
if (waveFormat->nSamplesPerSec != Miniport->stream[AC3_OUT_STREAM]->currentSampleRate) {
return STATUS_UNSUCCESSFUL;
}
}
if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[PCM_IN_STREAM]) {
if (waveFormat->nSamplesPerSec != Miniport->stream[PCM_IN_STREAM]->currentSampleRate) {
return STATUS_UNSUCCESSFUL;
}
}
if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
return STATUS_UNSUCCESSFUL;
}
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
currentSampleRate = waveFormat->nSamplesPerSec;
currentChannelCount = waveFormat->nChannels;
currentResolution = waveFormat->wBitsPerSample;
enableAC3Passthru = (WAVE_FORMAT_DOLBY_AC3_SPDIF == EXTRACT_WAVEFORMATEX_ID(&Format->SubFormat));
KeReleaseMutex(&Miniport->mutex, false);
ntStatus = prepareStream();
return ntStatus;
}
// DRM crap - we're supposed to disable every digital interface here
STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::SetContentId(ULONG contentId, PCDRMRIGHTS drmRights)
{
PAGED_CODE();
DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId, drmRights));
return STATUS_SUCCESS;
}
#ifdef WAVERT
STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size, PMDL *userModeBuffer, ULONG *bufferSize, ULONG *bufferOffset, MEMORY_CACHING_TYPE *cacheType)
{
PAGED_CODE();
PHYSICAL_ADDRESS low;
PHYSICAL_ADDRESS high;
DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(%x, %p, %p, %p, %p)", this, size, userModeBuffer, bufferSize, bufferOffset, cacheType));
if (size <= size % (currentChannelCount * 2)) {
return STATUS_UNSUCCESSFUL;
}
size -= size % (currentChannelCount * 2);
if (size == 0) {
return STATUS_UNSUCCESSFUL;
}
low.QuadPart = 0;
high.HighPart = 0, high.LowPart = MAXULONG;
audioBufferMDL = Port->AllocateContiguousPagesForMdl(low, high, size);
if (!audioBufferMDL) {
DBGPRINT(("AllocateContiguousPagesForMdl() failed"));
return STATUS_UNSUCCESSFUL;
}
dmaAddress = Port->GetPhysicalPageAddress(audioBufferMDL, 0).LowPart;
dmaMemorySize = size;
*userModeBuffer = audioBufferMDL;
*bufferSize = size;
*bufferOffset = 0;
*cacheType = MmCached;
return STATUS_SUCCESS;
}
STDMETHODIMP_(VOID) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl, ULONG Size)
{
PAGED_CODE();
DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl, Size));
Port->FreePagesFromMdl(Mdl);
audioBufferMDL = NULL;
dmaAddress = 0;
dmaMemorySize = 0;
}
STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency) {
PAGED_CODE();
DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency));
hwLatency->FifoSize = 32;
hwLatency->ChipsetDelay = 0;
hwLatency->CodecDelay = 4;
}
STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister)
{
PAGED_CODE();
DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister));
return STATUS_UNSUCCESSFUL;
}
STDMETHODIMP_(NTSTATUS) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister)
{
PAGED_CODE();
DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister));
return STATUS_UNSUCCESSFUL;
}
#endif // WAVERT
#pragma code_seg()
STDMETHODIMP CMiniportWaveStreamCMI::SetState(KSSTATE NewState)
{
DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d)", this, NewState));
UInt32 inthld, chen, reset, pause;
UInt8 reg;
inthld = EN_CH0_INT << channelNumber;
chen = EN_CH0 << channelNumber;
reset = RST_CH0 << channelNumber;
pause = PAUSE_CH0 << channelNumber;
NTSTATUS ntStatus = STATUS_SUCCESS;
if ((streamIndex == PCM_OUT_STREAM) && Miniport->isStreamRunning[AC3_OUT_STREAM]) {
return STATUS_INVALID_PARAMETER;
}
if (NewState == KSSTATE_RUN_AC3) {
NewState = state;
state = KSSTATE_STOP;
}
// STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP
if (state != NewState) {
switch (NewState) {
case KSSTATE_ACQUIRE:
DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state));
if (state == KSSTATE_PAUSE) {
break;
}
#ifdef WAVERT
if ((dmaMemorySize == 0) || (dmaAddress == 0)) {
return STATUS_UNSUCCESSFUL;
}
dmaSize = (dmaMemorySize / (2 * (currentResolution >> 3)) );
periodSize = dmaSize;
DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress, dmaMemorySize, dmaSize));
#else
if (currentResolution == 24) {
dmaSize = (DMAChannel->BufferSize() / (2 * (24 >> 3)) );
} else {
dmaSize = (DMAChannel->BufferSize() / (2 * (currentResolution >> 3)) );
}
#endif
DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex, channelNumber));
DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate, currentResolution, currentChannelCount));
if (periodSize > dmaSize) {
periodSize = dmaSize;
}
// set address of the DMA buffer
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
reg = channelNumber ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
#ifdef WAVERT
Miniport->CMIAdapter->writeUInt32(reg, dmaAddress);
#else
Miniport->CMIAdapter->writeUInt32(reg, DMAChannel->PhysicalAddress().u.LowPart);
#endif
// count of samples
reg = channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2;
Miniport->CMIAdapter->writeUInt16(reg, dmaSize-1);
Miniport->CMIAdapter->writeUInt16(reg + 2, periodSize-1);
DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize, periodSize, Miniport->cm->enableSPDIFIn));
if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) {
#if OUT_CHANNEL==0
Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_1);
#else
Miniport->CMIAdapter->setUInt32Bit(REG_FUNCTRL1, SPDF_0);
#endif
}
KeReleaseMutex(&Miniport->mutex, false);
break;
case KSSTATE_PAUSE:
DBGPRINT(("---KSSTATE_PAUSE: previous state: %d", state));
if (state == KSSTATE_RUN) {
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
Miniport->cm->regFUNCTRL0 |= pause;
Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
KeReleaseMutex(&Miniport->mutex, FALSE);
}
if (state == KSSTATE_STOP) {
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, false, NULL);
Miniport->cm->regFUNCTRL0 &= ~pause;
Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
KeReleaseMutex(&Miniport->mutex, false);
}
break;
case KSSTATE_RUN:
DBGPRINT(("---KSSTATE_RUN: previous state: %d", state));
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
// set interrupt
Miniport->CMIAdapter->setUInt32Bit(REG_INTHLDCLR, inthld);
Miniport->cm->regFUNCTRL0 &= ~pause;
Miniport->cm->regFUNCTRL0 |= chen;
// and enable the channel
Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0);
DBGPRINT(("---FUNCTRL0: 0x%08X", Miniport->cm->regFUNCTRL0));
DBGPRINT(("---FUNCTRL1: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_FUNCTRL1)));
DBGPRINT(("---CHFORMAT: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_CHFORMAT)));
DBGPRINT(("---LEGACYCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_LEGACY)));
DBGPRINT(("---MISCCTRL: 0x%08X", Miniport->CMIAdapter->readUInt32(REG_MISCCTRL)));
DBGPRINT(("---MIX1: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER1)));
DBGPRINT(("---MIX2: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER2)));
DBGPRINT(("---MIX3: 0x%02X", Miniport->CMIAdapter->readUInt8(REG_MIXER3)));
KeReleaseMutex(&Miniport->mutex, false);
break;
case KSSTATE_STOP_AC3:
case KSSTATE_STOP:
DBGPRINT(("---KSSTATE_STOP: previous state: %d", state));
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
// clear interrupt
Miniport->CMIAdapter->clearUInt32Bit(REG_INTHLDCLR, inthld);
Miniport->cm->regFUNCTRL0 &= ~chen;
// reset
Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 | reset);
Miniport->CMIAdapter->writeUInt32(REG_FUNCTRL0, Miniport->cm->regFUNCTRL0 & ~reset);
if (isCaptureStream && (Miniport->cm->enableSPDIFIn)) {
#if OUT_CHANNEL==0
Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_1);
#else
Miniport->CMIAdapter->clearUInt32Bit(REG_FUNCTRL1, SPDF_0);
#endif
}
KeReleaseMutex(&Miniport->mutex, FALSE);
break;
}
if (NewState != KSSTATE_STOP_AC3) {
state = NewState;
}
}
return ntStatus;
}
#ifdef WAVERT
STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position)
{
ASSERT(Position);
UInt32 reg;
if ((state == KSSTATE_RUN) && (dmaAddress)) {
reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
Position->PlayOffset = Miniport->CMIAdapter->readUInt32(reg) - dmaAddress;
Position->WriteOffset = Position->PlayOffset + currentChannelCount * 2 * 8;
} else {
Position->PlayOffset = 0;
Position->WriteOffset = 0;
}
return STATUS_SUCCESS;
}
#else //WaveCyclic
STDMETHODIMP CMiniportWaveStreamCMI::GetPosition(PULONG Position)
{
ASSERT(Position);
UInt32 reg;
if ((DMAChannel) && (state == KSSTATE_RUN)) {
#if 0
// this implementation messes with SPDIF-in recording
reg = (channelNumber) ? REG_CH1_FRAME2 : REG_CH0_FRAME2;
*Position = dmaSize - (Miniport->CMIAdapter->readUInt16(reg)-1);
*Position *= 2 * (currentResolution >> 3);
#else
reg = (channelNumber) ? REG_CH1_FRAME1 : REG_CH0_FRAME1;
*Position = Miniport->CMIAdapter->readUInt32(reg);
if (*Position > DMAChannel->PhysicalAddress().u.LowPart) {
*Position -= DMAChannel->PhysicalAddress().u.LowPart;
} else {
*Position = 0;
}
#endif
} else {
*Position = 0;
}
return STATUS_SUCCESS;
}
STDMETHODIMP_(ULONG) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval, PULONG FramingSize)
{
Miniport->notificationInterval = Interval;
if (state == KSSTATE_RUN) {
return 0;
}
periodSize = Interval * currentSampleRate/1000;
*FramingSize = periodSize*currentChannelCount*(currentResolution >> 3);
KeWaitForSingleObject(&Miniport->mutex, Executive, KernelMode, FALSE, NULL);
Miniport->CMIAdapter->writeUInt16((channelNumber ? REG_CH1_FRAME2 : REG_CH0_FRAME2) + 2, periodSize-1);
KeReleaseMutex(&Miniport->mutex, FALSE);
DBGPRINT(("periodSize: %x, FramingSize: %x", periodSize, *FramingSize));
return Interval;
}
STDMETHODIMP CMiniportWaveStreamCMI::NormalizePhysicalPosition(OUT PLONGLONG PhysicalPosition)
{
*PhysicalPosition = (_100NS_UNITS_PER_SECOND / currentChannelCount * (currentResolution >> 3) * *PhysicalPosition) / currentSampleRate;
return STATUS_SUCCESS;
}
STDMETHODIMP_(void) CMiniportWaveStreamCMI::Silence(PVOID Buffer, ULONG ByteCount)
{
RtlFillMemory(Buffer, ByteCount, 0x00);
}
#endif //WAVERT
STDMETHODIMP_(void) CMiniportWaveCMI::ServiceWaveISR(UInt32 streamIndex)
{
#ifndef WAVERT
if ((streamIndex == PCM_OUT_STREAM) && isStreamRunning[AC3_OUT_STREAM]) {
streamIndex = AC3_OUT_STREAM;
}
if (Port && stream[streamIndex]->ServiceGroup) {
Port->Notify(stream[streamIndex]->ServiceGroup);
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -