[ros-diffs] [janderwald] 49457: [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...

janderwald at svn.reactos.org janderwald at svn.reactos.org
Wed Nov 3 11:16:35 UTC 2010


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?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/topology.c?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/portcls/interfaces.hpp?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/portcls/irpstream.cpp?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/portcls/pin_dmus.cpp?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/portcls/pin_wavecyclic.cpp?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/portcls/pin_wavepci.cpp?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/portcls/pin_wavert.cpp?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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/wdmaud/control.c?rev=49457&r1=49456&r2=49457&view=diff
==============================================================================
--- 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 */




More information about the Ros-diffs mailing list