mirror of
https://github.com/reactos/reactos.git
synced 2024-08-03 10:00:56 +00:00
[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:
parent
a5f9cb6d11
commit
6793ef9a7c
|
@ -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];
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in a new issue