[PORTCLS]

- Implement support for submitting multiple stream headers at once
- Return correct status code on error
[WDMAUD_KERNEL]
- Save correct length

svn path=/trunk/; revision=43665
This commit is contained in:
Johannes Anderwald 2009-10-21 06:34:24 +00:00
parent a5f9cb6d11
commit 6793ef9a7c
4 changed files with 131 additions and 41 deletions

View file

@ -57,6 +57,16 @@ protected:
}; };
#define OFFSET_HEADERINDEX (0)
#define OFFSET_STREAMHEADER (2)
#define OFFSET_HEADERCOUNT (3)
#define STREAMHEADER_INDEX(Irp) (PtrToUlong(Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX]))
#define STREAMHEADER_COUNT(Irp) (PtrToUlong(Irp->Tail.Overlay.DriverContext[OFFSET_HEADERCOUNT]))
#define STREAMHEADER_CURRENT(Irp) (Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER])
NTSTATUS NTSTATUS
NTAPI NTAPI
CIrpQueue::QueryInterface( CIrpQueue::QueryInterface(
@ -107,6 +117,8 @@ CIrpQueue::AddMapping(
PKSSTREAM_HEADER Header; PKSSTREAM_HEADER Header;
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IoStack; PIO_STACK_LOCATION IoStack;
ULONG NumHeaders, NumData, Index;
PMDL Mdl;
PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
@ -132,31 +144,71 @@ CIrpQueue::AddMapping(
return Status; return Status;
} }
} }
// get the stream header
// get first stream header
Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
PC_ASSERT(Header);
PC_ASSERT(Irp->MdlAddress);
DPRINT("Size %u DataUsed %u FrameExtent %u SizeHeader %u NumDataAvailable %u OutputLength %u\n", Header->Size, Header->DataUsed, Header->FrameExtent, sizeof(KSSTREAM_HEADER), m_NumDataAvailable, IoStack->Parameters.DeviceIoControl.OutputBufferLength); // calculate num headers
NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
Header->Data = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); // assume headers of same length
PC_ASSERT(Header->Data); PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0);
//PC_ASSERT(Header->Size == IoStack->Parameters.DeviceIoControl.OutputBufferLength);
// HACK
Irp->Tail.Overlay.DriverContext[2] = (PVOID)Header;
// sanity check // get first audio buffer
PC_ASSERT(Header); Mdl = Irp->MdlAddress;
// dont exceed max frame size
//PC_ASSERT(m_MaxFrameSize >= Header->DataUsed);
// increment num mappings // store the current stream header
InterlockedIncrement(&m_NumMappings); Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER] = (PVOID)Header;
// store header count
Irp->Tail.Overlay.DriverContext[OFFSET_HEADERCOUNT] = UlongToPtr(NumHeaders);
// store current header index
Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
NumData = 0;
// prepare all headers
for(Index = 0; Index < NumHeaders; Index++)
{
// sanity checks
PC_ASSERT(Header);
PC_ASSERT(Mdl);
Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
if (!Header->Data)
{
// insufficient resources
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
Irp->AssociatedIrp.SystemBuffer = NULL;
// complete and forget request
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
// increment num mappings
InterlockedIncrement(&m_NumMappings);
// increment available data
InterlockedExchangeAdd((PLONG)&m_NumDataAvailable,
(max(Header->DataUsed, Header->FrameExtent)));
NumData += max(Header->DataUsed, Header->FrameExtent);
// move to next header
Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size);
// move to next mdl
Mdl = Mdl->Next;
}
DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable);
// increment num data available
m_NumDataAvailable += Header->DataUsed;
// mark irp as pending // mark irp as pending
IoMarkIrpPending(Irp); IoMarkIrpPending(Irp);
@ -206,6 +258,7 @@ CIrpQueue::GetMapping(
if (!Irp) if (!Irp)
{ {
DPRINT("NoIrp\n"); DPRINT("NoIrp\n");
return STATUS_UNSUCCESSFUL;
// no irp available, use silence buffer // no irp available, use silence buffer
*Buffer = (PUCHAR)m_SilenceBuffer; *Buffer = (PUCHAR)m_SilenceBuffer;
*BufferSize = m_MaxFrameSize; *BufferSize = m_MaxFrameSize;
@ -216,16 +269,8 @@ CIrpQueue::GetMapping(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
#if 0
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// get stream header // get stream header
StreamHeader = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
#else
// HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
#endif
// sanity check // sanity check
PC_ASSERT(StreamHeader); PC_ASSERT(StreamHeader);
@ -253,7 +298,7 @@ CIrpQueue::UpdateMapping(
IN ULONG BytesWritten) IN ULONG BytesWritten)
{ {
PKSSTREAM_HEADER StreamHeader; PKSSTREAM_HEADER StreamHeader;
ULONG Size; ULONG Size, NumData, Index;
if (!m_Irp) if (!m_Irp)
{ {
@ -262,7 +307,7 @@ CIrpQueue::UpdateMapping(
} }
// get stream header // get stream header
StreamHeader = (PKSSTREAM_HEADER)m_Irp->Tail.Overlay.DriverContext[2]; StreamHeader = (PKSSTREAM_HEADER)STREAMHEADER_CURRENT(m_Irp);
// sanity check // sanity check
// ASSERT(StreamHeader); // ASSERT(StreamHeader);
@ -282,20 +327,59 @@ CIrpQueue::UpdateMapping(
if (m_CurrentOffset >= Size) if (m_CurrentOffset >= Size)
{ {
if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp))
{
// the irp has at least one more stream header
m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1);
// get next stream header
StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
// store next stream header
STREAMHEADER_CURRENT(m_Irp) = (PVOID)StreamHeader;
// reset current offset
m_CurrentOffset = 0;
// done
return;
}
// irp has been processed completly // irp has been processed completly
NumData = 0;
StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
// loop all stream headers
for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++)
{
PC_ASSERT(StreamHeader);
// add size of buffer
// depends on if the buffer is input / output
if (StreamHeader->DataUsed)
Size = StreamHeader->DataUsed;
else
Size = StreamHeader->FrameExtent;
// increment size
NumData += Size;
// get next stream header
StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
}
m_Irp->IoStatus.Status = STATUS_SUCCESS; m_Irp->IoStatus.Status = STATUS_SUCCESS;
m_Irp->IoStatus.Information = NumData;
// frame extend contains the original request size, DataUsed contains the real buffer size #if 0
//is different when kmixer performs channel conversion, upsampling etc
m_Irp->IoStatus.Information = Size;
PC_ASSERT_IRQL(DISPATCH_LEVEL); PC_ASSERT_IRQL(DISPATCH_LEVEL);
MmUnlockPages(m_Irp->MdlAddress); MmUnlockPages(m_Irp->MdlAddress);
IoFreeMdl(m_Irp->MdlAddress); IoFreeMdl(m_Irp->MdlAddress);
m_Irp->MdlAddress = NULL; m_Irp->MdlAddress = NULL;
ExFreePool(m_Irp->AssociatedIrp.SystemBuffer); ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
m_Irp->AssociatedIrp.SystemBuffer = NULL; m_Irp->AssociatedIrp.SystemBuffer = NULL;
#endif
// complete the request // complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT); IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
@ -391,6 +475,9 @@ CIrpQueue::GetMappingWithTag(
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
} }
//FIXME support more than one stream header
PC_ASSERT(STREAMHEADER_COUNT(Irp) == 1);
// HACK get stream header // HACK get stream header
StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2]; StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];

View file

@ -601,10 +601,11 @@ CPortPinWaveCyclic::HandleKsStream(
else else
m_Position.WriteOffset += Header->DataUsed; m_Position.WriteOffset += Header->DataUsed;
return STATUS_PENDING;
} }
return Status;
return STATUS_PENDING;
} }
NTSTATUS NTSTATUS
@ -976,6 +977,11 @@ CPortPinWaveCyclic::Init(
RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize); RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
PKSDATAFORMAT_WAVEFORMATEX Wave = (PKSDATAFORMAT_WAVEFORMATEX)m_Format;
DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", Wave->WaveFormatEx.wBitsPerSample, Wave->WaveFormatEx.nSamplesPerSec, Wave->WaveFormatEx.nChannels, Wave->WaveFormatEx.wFormatTag, m_FrameSize);
Port->AddRef(); Port->AddRef();
Filter->AddRef(); Filter->AddRef();
@ -985,9 +991,6 @@ CPortPinWaveCyclic::Init(
DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE)); DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE)); DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
DPRINT("Setting state to run %x\n", m_Stream->SetState(KSSTATE_RUN));
m_State = KSSTATE_RUN;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -682,10 +682,10 @@ CPortPinWavePci::HandleKsStream(
else else
m_Position.WriteOffset += Header->DataUsed; m_Position.WriteOffset += Header->DataUsed;
return STATUS_PENDING;
} }
return Status;
return STATUS_PENDING;
} }

View file

@ -331,7 +331,7 @@ WdmAudReadWrite(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("KsProbeStreamIrp failed with Status %x\n", Status); DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel);
return SetIrpIoStatus(Irp, Status, 0); return SetIrpIoStatus(Irp, Status, 0);
} }
@ -355,7 +355,7 @@ WdmAudReadWrite(
/* attach file object */ /* attach file object */
IoStack->FileObject = FileObject; IoStack->FileObject = FileObject;
IoStack->Parameters.Write.Length = sizeof(KSSTREAM_HEADER); IoStack->Parameters.Write.Length = Length;
IoStack->MajorFunction = IRP_MJ_WRITE; IoStack->MajorFunction = IRP_MJ_WRITE;
/* mark irp as pending */ /* mark irp as pending */