Author: janderwald
Date: Wed Nov 3 11:16:33 2010
New Revision: 49457
URL:
http://svn.reactos.org/svn/reactos?rev=49457&view=rev
Log:
[KS]
- Fix several bugs in KsProbeStreamIrp
- If requestor is KernelMode - just save a pointer in Irp->AssociatedIrp.SystemBuffer
(currently not used)
- If requestor is UserMode mark irp as buffered. Also set Flag IRP_INPUT_OPERATION when
the ioctl is IOCTL_KS_READ_STREAM. This is important to propagate modifications to
KSSTREAM_HEADERS (in particular DataUsed member)
- ReactOS KS can now be used in WinXP in combination with KSStudio. In order to make it
fully work, ks needs to implement software bus functions
[PORTCLS]
- Rewrite internal irp queue handling
- It now supports multiple KSSTREAM_HEADERs per Irp, variable sized KSSTREAM_HEADERs per
irp.
- Store the mapped virtual address not in the KSSTREAM_HEADER, as user programs will
receive then invalid addresses
- Add checks whether this irp is for an sink pin or source pin
- Fix multiple bugs when the pin is looped buffer mode (How did this work before?)
- ReactOS portcls + WinXP now properly works with audio recording
[WDMAUD_KERNEL]
- Don't free associated stream header anymore
- Tested with VBox 3.2.10 + VmWare Player 3.1.2 + WinXP
Modified:
trunk/reactos/drivers/ksfilter/ks/irp.c
trunk/reactos/drivers/ksfilter/ks/topology.c
trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp
trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
Modified: trunk/reactos/drivers/ksfilter/ks/irp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/irp.c?…
==============================================================================
--- trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/ksfilter/ks/irp.c [iso-8859-1] Wed Nov 3 11:16:33 2010
@@ -661,6 +661,11 @@
if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer)
{
+ if (Irp->RequestorMode == KernelMode)
+ {
+ /* no need to allocate stream header */
+ Irp->AssociatedIrp.SystemBuffer = Irp->UserBuffer;
+ }
AllocMdl:
/* check if alloc mdl flag is passed */
if (!(ProbeFlags & KSPROBE_ALLOCATEMDL))
@@ -910,6 +915,9 @@
return STATUS_INSUFFICIENT_RESOURCES;
}
+ /* mark irp as buffered so that changes the stream headers are propagated back
*/
+ Irp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
+
_SEH2_TRY
{
if (ProbeFlags & KSPROBE_STREAMWRITE)
@@ -923,6 +931,9 @@
{
/* stream reads means writing */
ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR));
+
+ /* set input operation flags */
+ Irp->Flags |= IRP_INPUT_OPERATION;
}
/* copy stream buffer */
Modified: trunk/reactos/drivers/ksfilter/ks/topology.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/ksfilter/ks/topolo…
==============================================================================
--- trunk/reactos/drivers/ksfilter/ks/topology.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/ksfilter/ks/topology.c [iso-8859-1] Wed Nov 3 11:16:33 2010
@@ -38,7 +38,7 @@
return STATUS_INSUFFICIENT_RESOURCES;
}
- /* build a request which looks like \{ObjectClass}\CreateParameters
+ /* build a request which looks like {ObjectClass}\CreateParameters
* For pins the parent is the reference string used in registration
* For clocks it is full path for pin\{ClockGuid}\ClockCreateParams
*/
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp [iso-8859-1]
(original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp [iso-8859-1] Wed Nov 3
11:16:33 2010
@@ -319,9 +319,11 @@
DEFINE_ABSTRACT_UNKNOWN()
STDMETHOD_(NTSTATUS, Init)(THIS_
- IN KSPIN_CONNECT *ConnectDetails,
+ IN PKSPIN_CONNECT ConnectDetails,
+ IN PKSPIN_DESCRIPTOR Descriptor,
IN ULONG FrameSize,
- IN ULONG Alignment) PURE;
+ IN ULONG Alignment,
+ IN ULONG TagSupportEnabled) PURE;
STDMETHOD_(NTSTATUS, AddMapping)(THIS_
IN PIRP Irp,
@@ -360,9 +362,11 @@
#define IMP_IIrpQueue \
STDMETHODIMP_(NTSTATUS) Init(THIS_ \
- IN KSPIN_CONNECT *ConnectDetails, \
+ IN PKSPIN_CONNECT ConnectDetails, \
+ IN PKSPIN_DESCRIPTOR Descriptor, \
IN ULONG FrameSize, \
- IN ULONG Alignment); \
+ IN ULONG Alignment, \
+ IN ULONG TagSupportEnabled); \
\
STDMETHODIMP_(NTSTATUS) AddMapping(THIS_ \
IN PIRP Irp, \
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp [iso-8859-1] Wed Nov 3
11:16:33 2010
@@ -35,31 +35,40 @@
virtual ~CIrpQueue(){}
protected:
- volatile ULONG m_CurrentOffset;
- LONG m_NumMappings;
- ULONG m_NumDataAvailable;
+
PKSPIN_CONNECT m_ConnectDetails;
+ PKSPIN_DESCRIPTOR m_Descriptor;
+
KSPIN_LOCK m_IrpListLock;
LIST_ENTRY m_IrpList;
LIST_ENTRY m_FreeIrpList;
- PIRP m_Irp;
ULONG m_OutOfMapping;
ULONG m_MaxFrameSize;
ULONG m_Alignment;
+ ULONG m_TagSupportEnabled;
+ ULONG m_NumDataAvailable;
+ volatile ULONG m_CurrentOffset;
+
+ PIRP m_Irp;
+
LONG m_Ref;
};
-#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])
+typedef struct
+{
+ ULONG StreamHeaderCount;
+ ULONG StreamHeaderIndex;
+ ULONG TotalStreamData;
+
+ PKSSTREAM_HEADER CurStreamHeader;
+ PVOID * Data;
+ PVOID * Tags;
+}KSSTREAM_DATA, *PKSSTREAM_DATA;
+
+#define STREAM_DATA_OFFSET (0)
NTSTATUS
@@ -81,13 +90,17 @@
NTSTATUS
NTAPI
CIrpQueue::Init(
- IN KSPIN_CONNECT *ConnectDetails,
+ IN PKSPIN_CONNECT ConnectDetails,
+ IN PKSPIN_DESCRIPTOR Descriptor,
IN ULONG FrameSize,
- IN ULONG Alignment)
+ IN ULONG Alignment,
+ IN ULONG TagSupportEnabled)
{
m_ConnectDetails = ConnectDetails;
+ m_Descriptor = Descriptor;
m_MaxFrameSize = FrameSize;
m_Alignment = Alignment;
+ m_TagSupportEnabled = TagSupportEnabled;
InitializeListHead(&m_IrpList);
InitializeListHead(&m_FreeIrpList);
@@ -103,110 +116,158 @@
OUT PULONG Data)
{
PKSSTREAM_HEADER Header;
- NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
PIO_STACK_LOCATION IoStack;
- ULONG NumHeaders, NumData, Index;
+ ULONG Index, Length;
PMDL Mdl;
+ PKSSTREAM_DATA StreamData;
PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ // allocate stream data
+ StreamData = (PKSSTREAM_DATA)AllocateItem(NonPagedPool, sizeof(KSSTREAM_DATA),
TAG_PORTCLASS);
+ if (!StreamData)
+ {
+ // not enough memory
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
- if (!Irp->MdlAddress)
- {
- // ioctl from KsStudio
- // Wdmaud already probes buffers, therefore no need to probe it again
- // probe the stream irp
- if (IoStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_KS_WRITE_STREAM)
- Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL |
KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
- else if (IoStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_KS_READ_STREAM)
- Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL |
KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
- else
- PC_ASSERT(0);
-
- // check for success
- if (!NT_SUCCESS(Status))
- {
- DPRINT("KsProbeStreamIrp failed with %x\n", Status);
- return Status;
- }
+ // lets probe the irp
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
+ {
+ // probe IOCTL_KS_WRITE_STREAM
+ Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL |
KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
+ }
+ else if (IoStack->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_KS_READ_STREAM)
+ {
+ // probe IOCTL_KS_READ_STREAM
+ Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL |
KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, 0);
+ }
+
+ // check for success
+ if (!NT_SUCCESS(Status))
+ {
+ // irp probing failed
+ FreeItem(StreamData, TAG_PORTCLASS);
+ return Status;
}
// get first stream header
-
- if (Irp->RequestorMode == UserMode)
- Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
- else
- Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
+ Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+
+ // store header
+ StreamData->CurStreamHeader = Header;
// sanity check
PC_ASSERT(Header);
- // calculate num headers
- NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength /
Header->Size;
-
- // assume headers of same length
- PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size
== 0);
-
-
- // get first audio buffer
+ // first calculate the numbers of stream headers
+ Length = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+
+ do
+ {
+ /* subtract size */
+ Length -= Header->Size;
+
+ /* increment header count */
+ StreamData->StreamHeaderCount++;
+
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ // irp sink
+ StreamData->TotalStreamData += Header->DataUsed;
+ }
+ else
+ {
+ // irp source
+ StreamData->TotalStreamData += Header->FrameExtent;
+ }
+
+ /* move to next header */
+ Header = (PKSSTREAM_HEADER)((ULONG_PTR)Header + Header->Size);
+
+ }while(Length);
+
+ // sanity check
+ ASSERT(StreamData->StreamHeaderCount);
+
+ // allocate array for storing the pointers of the data */
+ StreamData->Data = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) *
StreamData->StreamHeaderCount, TAG_PORTCLASS);
+ if (!StreamData->Data)
+ {
+ // out of memory
+ FreeItem(StreamData, TAG_PORTCLASS);
+
+ // done
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if (m_TagSupportEnabled)
+ {
+ // allocate array for storing the pointers of the data */
+ StreamData->Tags = (PVOID*)AllocateItem(NonPagedPool, sizeof(PVOID) *
StreamData->StreamHeaderCount, TAG_PORTCLASS);
+ if (!StreamData->Data)
+ {
+ // out of memory
+ FreeItem(StreamData->Data, TAG_PORTCLASS);
+ FreeItem(StreamData, TAG_PORTCLASS);
+
+ // done
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+
+ // now get a system address for the user buffers
+ Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
Mdl = Irp->MdlAddress;
- // sanity check
- PC_ASSERT(Mdl);
-
- // store the current stream header
- 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);
-
- if (Irp->RequestorMode == UserMode)
- {
- 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);
+
+ for(Index = 0; Index < StreamData->StreamHeaderCount; Index++)
+ {
+ /* get system address */
+ StreamData->Data[Index] = MmGetSystemAddressForMdlSafe(Mdl,
NormalPagePriority);
+
+ /* check for success */
+ if (!StreamData->Data[Index])
+ {
+ // out of resources
+ FreeItem(StreamData->Data, TAG_PORTCLASS);
+
+ if (m_TagSupportEnabled)
+ {
+ // free tag array
+ FreeItem(StreamData->Tags, TAG_PORTCLASS);
+ }
+
+ FreeItem(StreamData, TAG_PORTCLASS);
+ // done
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
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ // increment available data
+ InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, Header->DataUsed);
+ }
+ else if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT)
+ {
+ // increment available data
+ InterlockedExchangeAdd((PLONG)&m_NumDataAvailable,
Header->FrameExtent);
+ }
+
+ // move to next header / mdl
+ Mdl = Mdl->Next;
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);
- *Data = NumData;
+
+ }
+
+ // store stream data
+ Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET] = (PVOID)StreamData;
+
+ *Data = StreamData->TotalStreamData;
// mark irp as pending
IoMarkIrpPending(Irp);
@@ -218,7 +279,7 @@
m_OutOfMapping = FALSE;
// done
- return Status;
+ return STATUS_SUCCESS;
}
NTSTATUS
@@ -229,8 +290,7 @@
{
PIRP Irp;
ULONG Offset;
- //PIO_STACK_LOCATION IoStack;
- PKSSTREAM_HEADER StreamHeader;
+ PKSSTREAM_DATA StreamData;
// check if there is an irp in the partially processed
if (m_Irp)
@@ -247,6 +307,7 @@
m_Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(m_Irp, IO_NO_INCREMENT);
m_Irp = Irp = NULL;
+ m_CurrentOffset = 0;
}
}
else
@@ -259,26 +320,32 @@
if (!Irp)
{
// no irp buffer available
- DPRINT("NoIrp\n");
return STATUS_UNSUCCESSFUL;
}
- // get stream header
- StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
-
- // sanity check
- PC_ASSERT(StreamHeader);
-
- // store buffersize
- if (StreamHeader->DataUsed)
- *BufferSize = StreamHeader->DataUsed - Offset;
+ // get stream data
+ StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
+
+ // sanity check
+ PC_ASSERT(StreamData);
+
+ // get buffer size
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ // sink pin
+ *BufferSize = StreamData->CurStreamHeader->DataUsed - Offset;
+ }
else
- *BufferSize = StreamHeader->FrameExtent - Offset;
-
+ {
+ // source pin
+ *BufferSize = StreamData->CurStreamHeader->FrameExtent - Offset;
+ }
+
+ // sanity check
PC_ASSERT(*BufferSize);
// store buffer
- *Buffer = &((PUCHAR)StreamHeader->Data)[Offset];
+ *Buffer =
&((PUCHAR)StreamData->Data[StreamData->StreamHeaderIndex])[Offset];
// unset flag that no irps are available
m_OutOfMapping = FALSE;
@@ -291,102 +358,111 @@
CIrpQueue::UpdateMapping(
IN ULONG BytesWritten)
{
- PKSSTREAM_HEADER StreamHeader;
- ULONG Size, NumData, Index;
-
- if (!m_Irp)
- {
- // silence buffer was used
- return;
- }
-
- // get stream header
- StreamHeader = (PKSSTREAM_HEADER)STREAMHEADER_CURRENT(m_Irp);
-
- // sanity check
- // ASSERT(StreamHeader);
+ PKSSTREAM_DATA StreamData;
+ ULONG Size;
+ PIO_STACK_LOCATION IoStack;
+
+ // sanity check
+ ASSERT(m_Irp);
+
+ // get stream data
+ StreamData =
(PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
+
+ // sanity check
+ ASSERT(StreamData);
// add to current offset
InterlockedExchangeAdd((volatile PLONG)&m_CurrentOffset, (LONG)BytesWritten);
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT)
+ {
+ // store written bytes (source pin)
+ StreamData->CurStreamHeader->DataUsed += BytesWritten;
+ }
+
// decrement available data counter
m_NumDataAvailable -= BytesWritten;
- if (StreamHeader->DataUsed)
- Size = StreamHeader->DataUsed;
+ // get audio buffer size
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_OUT)
+ Size = StreamData->CurStreamHeader->FrameExtent;
else
- Size = StreamHeader->FrameExtent;
-
+ Size = StreamData->CurStreamHeader->DataUsed;
+
+ // sanity check
PC_ASSERT(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
+ // sanity check
+ PC_ASSERT(Size == m_CurrentOffset);
+
+ if (StreamData->StreamHeaderIndex + 1 < StreamData->StreamHeaderCount)
+ {
+ // move to next stream header
+ StreamData->CurStreamHeader =
(PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader +
StreamData->CurStreamHeader->Size);
+
+ // increment stream header index
+ StreamData->StreamHeaderIndex++;
+
+ // reset offset
m_CurrentOffset = 0;
// done
return;
}
- // irp has been processed completly
- NumData = 0;
- if (m_Irp->RequestorMode == KernelMode)
- StreamHeader = (PKSSTREAM_HEADER)m_Irp->UserBuffer;
- else
- 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);
- }
-
+ //
+ // all stream buffers have been played
+ // check if this is a looped buffer
+ //
if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
{
// looped streaming repeat the buffers untill
// the caller decides to stop the streams
// reset stream header index
- m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
+ StreamData->StreamHeaderIndex = 0;
+
+ // reset stream header
+ StreamData->CurStreamHeader =
(PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
+
+ // increment available data
+ InterlockedExchangeAdd((PLONG)&m_NumDataAvailable,
StreamData->TotalStreamData);
+
// re-insert irp
KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp,
KsListEntryTail, NULL);
+
// clear current irp
m_Irp = NULL;
+
// reset offset
m_CurrentOffset = 0;
- // increment available data
- InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, NumData);
+
// done
return;
}
+ // free stream data array
+ FreeItem(StreamData->Data, TAG_PORTCLASS);
+
+ if (m_TagSupportEnabled)
+ {
+ // free tag array
+ FreeItem(StreamData->Tags, TAG_PORTCLASS);
+ }
+
+ // free stream data
+ FreeItem(StreamData, TAG_PORTCLASS);
+
+ // get io stack
+ IoStack = IoGetCurrentIrpStackLocation(m_Irp);
+
// store operation status
m_Irp->IoStatus.Status = STATUS_SUCCESS;
- m_Irp->IoStatus.Information = 0;
+
+ // store operation length
+ m_Irp->IoStatus.Information =
IoStack->Parameters.DeviceIoControl.OutputBufferLength;
// complete the request
IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
@@ -411,6 +487,8 @@
NTAPI
CIrpQueue::CancelBuffers()
{
+ //TODO: own cancel routine
+
// is there an active irp
if (m_Irp)
{
@@ -422,8 +500,7 @@
// cancel all irps
KsCancelIo(&m_IrpList, &m_IrpListLock);
- // reset number of mappings
- m_NumMappings = 0;
+
// reset number of data available
m_NumDataAvailable = 0;
@@ -440,44 +517,83 @@
OUT PULONG ByteCount,
OUT PULONG Flags)
{
- PKSSTREAM_HEADER StreamHeader;
- PIRP Irp;
-
- *Flags = 0;
+ PKSSTREAM_DATA StreamData;
+
+ /* sanity checks */
PC_ASSERT(Tag != NULL);
-
- // get an irp from the queue
- Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock,
KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+ PC_ASSERT(PhysicalAddress);
+ PC_ASSERT(VirtualAddress);
+ PC_ASSERT(ByteCount);
+ PC_ASSERT(Flags);
+
+ if (!m_Irp)
+ {
+ // get an irp from the queue
+ m_Irp = KsRemoveIrpFromCancelableQueue(&m_IrpList, &m_IrpListLock,
KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+ }
// check if there is an irp
- if (!Irp)
+ if (!m_Irp)
{
// no irp available
m_OutOfMapping = TRUE;
return STATUS_NOT_FOUND;
}
- //FIXME support more than one stream header
- PC_ASSERT(STREAMHEADER_COUNT(Irp) == 1);
-
- // HACK get stream header
- StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
-
- // store mapping in the free list
- ExInterlockedInsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry,
&m_IrpListLock);
-
- // return mapping
- *PhysicalAddress = MmGetPhysicalAddress(StreamHeader->Data);
- *VirtualAddress = StreamHeader->Data;
- *ByteCount = StreamHeader->DataUsed;
-
- // decrement mapping count
- InterlockedDecrement(&m_NumMappings);
- // decrement num data available
- m_NumDataAvailable -= StreamHeader->DataUsed;
+ // get stream data
+ StreamData =
(PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
+
+ // sanity check
+ PC_ASSERT(StreamData->StreamHeaderIndex < StreamData->StreamHeaderCount);
+
+ // setup mapping
+ *PhysicalAddress =
MmGetPhysicalAddress(StreamData->Data[StreamData->StreamHeaderIndex]);
+ *VirtualAddress = StreamData->Data[StreamData->StreamHeaderIndex];
// store tag in irp
- Irp->Tail.Overlay.DriverContext[3] = Tag;
+ StreamData->Tags[StreamData->StreamHeaderIndex] = Tag;
+
+ // mapping size
+ if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ // sink pin
+ *ByteCount = StreamData->CurStreamHeader->DataUsed;
+
+ // decrement num data available
+ m_NumDataAvailable -= StreamData->CurStreamHeader->DataUsed;
+ }
+ else
+ {
+ // source pin
+ *ByteCount = StreamData->CurStreamHeader->FrameExtent;
+
+ // decrement num data available
+ m_NumDataAvailable -= StreamData->CurStreamHeader->FrameExtent;
+ }
+
+ if (StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount)
+ {
+ // last mapping
+ *Flags = 1;
+
+ // insert mapping into free list
+ ExInterlockedInsertTailList(&m_FreeIrpList,
&m_Irp->Tail.Overlay.ListEntry, &m_IrpListLock);
+
+ // clear irp
+ m_Irp = NULL;
+
+ }
+ else
+ {
+ // one more mapping in the irp
+ *Flags = 0;
+
+ // increment header index
+ StreamData->StreamHeaderIndex++;
+
+ // move to next header
+ StreamData->CurStreamHeader =
(PKSSTREAM_HEADER)((ULONG_PTR)StreamData->CurStreamHeader +
StreamData->CurStreamHeader->Size);
+ }
// done
return STATUS_SUCCESS;
@@ -490,34 +606,123 @@
{
PIRP Irp;
PLIST_ENTRY CurEntry;
- PKSSTREAM_HEADER StreamHeader;
-
- DPRINT("CIrpQueue::ReleaseMappingWithTag Tag %p\n", Tag);
+ PKSSTREAM_DATA StreamData;
+ PIO_STACK_LOCATION IoStack;
+ ULONG Index;
+
+ // first check if there is an active irp
+ if (m_Irp)
+ {
+ // now check if there are already used mappings
+ StreamData =
(PKSSTREAM_DATA)m_Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
+
+ if (StreamData->StreamHeaderIndex)
+ {
+ // check if the released mapping is one current processed irps
+ for(Index = 0; Index < StreamData->StreamHeaderIndex; Index++)
+ {
+ // check if it is the same tag
+ if (StreamData->Tags[Index] == Tag)
+ {
+ // mark mapping as released
+ StreamData->Tags[Index] = NULL;
+
+ // done
+ return STATUS_SUCCESS;
+ }
+
+ }
+ }
+ }
// remove irp from used list
CurEntry = ExInterlockedRemoveHeadList(&m_FreeIrpList, &m_IrpListLock);
+
// sanity check
PC_ASSERT(CurEntry);
// get irp from list entry
Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
- // HACK get stream header
- StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
-
- // driver must release items in the same order
- PC_ASSERT(Irp->Tail.Overlay.DriverContext[3] == Tag);
-
- // irp has been processed completly
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- // frame extend contains the original request size, DataUsed contains the real buffer
size
- // is different when kmixer performs channel conversion, upsampling etc
-
- Irp->IoStatus.Information = StreamHeader->FrameExtent;
-
- // complete the request
- IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
+ // get stream data
+ StreamData = (PKSSTREAM_DATA)Irp->Tail.Overlay.DriverContext[STREAM_DATA_OFFSET];
+
+ // sanity check
+ PC_ASSERT(StreamData->StreamHeaderIndex + 1 == StreamData->StreamHeaderCount);
+
+ // check if the released mapping is one of these
+ for(Index = 0; Index < StreamData->StreamHeaderCount; Index++)
+ {
+ if (StreamData->Tags[Index] == Tag)
+ {
+ // mark mapping as released
+ StreamData->Tags[Index] = NULL;
+
+ // done
+ break;
+ }
+ else
+ {
+ //
+ // we assume that mappings are released in the same order as they have been
acquired
+ // therefore if the current mapping is not the searched one, it must have
been already
+ // released
+ //
+ PC_ASSERT(StreamData->Tags[Index] == NULL);
+ }
+ }
+
+ // check if this is the last one released mapping
+ if (Index + 1 == StreamData->StreamHeaderCount)
+ {
+ // last mapping released
+ // now check if this is a looped buffer
+ if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+ {
+ // looped buffers are not completed when they have been played
+ // they are completed when the stream is set to stop
+
+ // reset stream header index
+ StreamData->StreamHeaderIndex = 0;
+
+ // reset stream header
+ StreamData->CurStreamHeader =
(PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+
+ // increment available data
+ InterlockedExchangeAdd((PLONG)&m_NumDataAvailable,
StreamData->TotalStreamData);
+
+ // re-insert irp
+ KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, Irp,
KsListEntryTail, NULL);
+
+ // done
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // time to complete non looped buffer
+ //
+
+ // free stream data array
+ FreeItem(StreamData->Data, TAG_PORTCLASS);
+
+ // free stream tags array
+ FreeItem(StreamData->Tags, TAG_PORTCLASS);
+
+ // free stream data
+ FreeItem(StreamData, TAG_PORTCLASS);
+
+ // get io stack
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ // store operation status
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ // store operation length
+ Irp->IoStatus.Information =
IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+
+ // complete the request
+ IoCompleteRequest(Irp, IO_SOUND_INCREMENT);
+ }
return STATUS_SUCCESS;
}
@@ -545,38 +750,18 @@
{
KIRQL OldLevel;
BOOLEAN Ret = FALSE;
- PIRP Irp;
- PLIST_ENTRY CurEntry;
-
+ //PIRP Irp;
+ //PLIST_ENTRY CurEntry;
+ //PKSSTREAM_DATA StreamData;
+
+ // lock list
KeAcquireSpinLock(&m_IrpListLock, &OldLevel);
- if (!IsListEmpty(&m_FreeIrpList))
- {
- // get first entry
- CurEntry = RemoveHeadList(&m_FreeIrpList);
- // get irp from list entry
- Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
-
- // get tag of first acquired buffer
- *FirstTag = Irp->Tail.Overlay.DriverContext[3];
-
- // put back irp
- InsertHeadList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry);
-
- // get last entry
- CurEntry = RemoveTailList(&m_FreeIrpList);
- // get irp from list entry
- Irp = (PIRP)CONTAINING_RECORD(CurEntry, IRP, Tail.Overlay.ListEntry);
-
- // get tag of first acquired buffer
- *LastTag = Irp->Tail.Overlay.DriverContext[3];
-
- // put back irp
- InsertTailList(&m_FreeIrpList, &Irp->Tail.Overlay.ListEntry);
-
- // indicate success
- Ret = TRUE;
- }
+ // initialize to zero
+ *FirstTag = NULL;
+ *LastTag = NULL;
+
+ UNIMPLEMENTED;
// release lock
KeReleaseSpinLock(&m_IrpListLock, OldLevel);
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.cpp [iso-8859-1] Wed Nov 3
11:16:33 2010
@@ -604,7 +604,7 @@
}
}
- Status = m_IrpQueue->Init(ConnectDetails, 0, 0);
+ Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("IrpQueue_Init failed with %x\n", Status);
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1]
(original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp [iso-8859-1] Wed
Nov 3 11:16:33 2010
@@ -702,7 +702,7 @@
if (Gap > BufferLength)
{
// insert silence samples
- DPRINT1("Inserting Silence Buffer Offset %lu GapLength %lu\n",
m_CommonBufferOffset, BufferLength);
+ DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n",
m_CommonBufferOffset, BufferLength);
m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
BufferLength);
m_CommonBufferOffset += BufferLength;
@@ -761,7 +761,7 @@
if (Gap > BufferLength)
{
// insert silence samples
- DPRINT1("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap
%lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position);
+ DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu
Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position);
m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
BufferLength);
m_CommonBufferOffset += BufferLength;
@@ -1303,7 +1303,7 @@
m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
- Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0);
+ Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_FrameSize, 0,
FALSE);
if (!NT_SUCCESS(Status))
{
m_IrpQueue->Release();
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp [iso-8859-1]
(original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp [iso-8859-1] Wed Nov
3 11:16:33 2010
@@ -919,7 +919,7 @@
}
// initialize irp queue
- Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize,
m_AllocatorFraming.FileAlignment);
+ Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor,
m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, TRUE);
if (!NT_SUCCESS(Status))
{
// this should never happen
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp [iso-8859-1]
(original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.cpp [iso-8859-1] Wed Nov 3
11:16:33 2010
@@ -283,7 +283,7 @@
CPortPinWaveRT::HandleKsStream(
IN PIRP Irp)
{
- DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n",
m_State, m_Stream);
+ DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p is
UNIMPLEMENTED\n", m_State, m_Stream);
return STATUS_PENDING;
}
@@ -587,7 +587,7 @@
goto cleanup;
}
- Status = m_IrpQueue->Init(ConnectDetails, 0, 0);
+ Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE);
if (!NT_SUCCESS(Status))
{
goto cleanup;
@@ -624,7 +624,7 @@
// delay of 10 milisec
m_Delay = Int32x32To64(10, -10000);
- Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl,
&m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
+ Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl,
&m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
if (!NT_SUCCESS(Status))
{
DPRINT("AllocateAudioBuffer failed with %x\n", Status);
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/w…
==============================================================================
--- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Wed Nov 3
11:16:33 2010
@@ -452,15 +452,17 @@
/* now free the mdl */
IoFreeMdl(Context->Mdl);
- /* now free the stream header */
- ExFreePool(Irp->AssociatedIrp.SystemBuffer);
-
DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx Length %lu\n",
Irp, Irp->IoStatus.Status, Irp->IoStatus.Information, Length);
if (Irp->IoStatus.Status == STATUS_SUCCESS)
{
/* store the length */
Irp->IoStatus.Information = Length;
+ }
+ else
+ {
+ /* failed */
+ Irp->IoStatus.Information = 0;
}
/* free context */