[PORTCLS]
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / irpstream.cpp
index f3b1d7b..aaa707b 100644 (file)
@@ -35,11 +35,11 @@ public:
     virtual ~CIrpQueue(){}
 
 protected:
-    ULONG m_CurrentOffset;
+    volatile ULONG m_CurrentOffset;
     LONG m_NumMappings;
     ULONG m_NumDataAvailable;
     BOOL m_StartStream;
-    KSPIN_CONNECT * m_ConnectDetails;
+    PKSPIN_CONNECT m_ConnectDetails;
     PKSDATAFORMAT_WAVEFORMATEX m_DataFormat;
 
     KSPIN_LOCK m_IrpListLock;
@@ -110,9 +110,8 @@ CIrpQueue::Init(
 NTSTATUS
 NTAPI
 CIrpQueue::AddMapping(
-    IN PUCHAR Buffer,
-    IN ULONG BufferSize,
-    IN PIRP Irp)
+    IN PIRP Irp,
+    OUT PULONG Data)
 {
     PKSSTREAM_HEADER Header;
     NTSTATUS Status = STATUS_SUCCESS;
@@ -125,8 +124,6 @@ CIrpQueue::AddMapping(
     // get current irp stack location
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    PC_ASSERT(!Buffer);
-
     if (!Irp->MdlAddress)
     {
         // ioctl from KsStudio
@@ -148,7 +145,14 @@ CIrpQueue::AddMapping(
     }
 
     // get first stream header
-    Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+
+   if (Irp->RequestorMode == UserMode)
+       Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
+   else
+       Header = (PKSSTREAM_HEADER)Irp->UserBuffer;
+
+    // sanity check
+    PC_ASSERT(Header);
 
     // calculate num headers
     NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
@@ -159,7 +163,8 @@ CIrpQueue::AddMapping(
 
     // get first audio buffer
     Mdl = Irp->MdlAddress;
-
+    // sanity check
+    PC_ASSERT(Mdl);
 
     // store the current stream header
     Irp->Tail.Overlay.DriverContext[OFFSET_STREAMHEADER] = (PVOID)Header;
@@ -169,29 +174,31 @@ CIrpQueue::AddMapping(
     // store current header index
     Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
 
-
     NumData = 0;
     // prepare all headers
-       for(Index = 0; Index < NumHeaders; Index++)
-       {
+    for(Index = 0; Index < NumHeaders; Index++)
+    {
         // sanity checks
         PC_ASSERT(Header);
         PC_ASSERT(Mdl);
 
-        Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
+        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
+            // 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);
@@ -207,10 +214,10 @@ CIrpQueue::AddMapping(
         
         // 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;
 
     // mark irp as pending
     IoMarkIrpPending(Irp);
@@ -260,7 +267,6 @@ CIrpQueue::GetMapping(
     if (!Irp)
     {
         DPRINT("NoIrp\n");
-        return STATUS_UNSUCCESSFUL;
         // no irp available, use silence buffer
         *Buffer = (PUCHAR)m_SilenceBuffer;
         *BufferSize = m_MaxFrameSize;
@@ -315,7 +321,7 @@ CIrpQueue::UpdateMapping(
    // ASSERT(StreamHeader);
 
     // add to current offset
-    m_CurrentOffset += BytesWritten;
+    InterlockedExchangeAdd((volatile PLONG)&m_CurrentOffset, (LONG)BytesWritten);
 
     // decrement available data counter
     m_NumDataAvailable -= BytesWritten;
@@ -330,7 +336,7 @@ CIrpQueue::UpdateMapping(
     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);
 
@@ -345,16 +351,19 @@ CIrpQueue::UpdateMapping(
 
             // done
             return;
-               }
+        }
 
-        // irp has been processed completly
+       // irp has been processed completly
 
         NumData = 0;
-        StreamHeader = (PKSSTREAM_HEADER)m_Irp->AssociatedIrp.SystemBuffer;
+        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
@@ -369,20 +378,30 @@ CIrpQueue::UpdateMapping(
 
             // get next stream header
             StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
-               }
+        }
+
+        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);
+            // 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;
+        }
 
         m_Irp->IoStatus.Status = STATUS_SUCCESS;
         m_Irp->IoStatus.Information = NumData;
 
-#if 0
-        PC_ASSERT_IRQL(DISPATCH_LEVEL);
-        MmUnlockPages(m_Irp->MdlAddress);
-        IoFreeMdl(m_Irp->MdlAddress);
-        m_Irp->MdlAddress = NULL;
-        ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
-        m_Irp->AssociatedIrp.SystemBuffer = NULL;
-#endif
-
         // complete the request
         IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
         // remove irp as it is complete
@@ -434,8 +453,20 @@ BOOL
 NTAPI
 CIrpQueue::CancelBuffers()
 {
+    // is there an active irp
+    if (m_Irp)
+    {
+        // re-insert it to cancelable queue
+        KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
+        //set it to zero
+        m_Irp = NULL;
+    }
 
+    // cancel all irps
+    KsCancelIo(&m_IrpList, &m_IrpListLock);
+    // reset stream start flag
     m_StartStream = FALSE;
+    // done
     return TRUE;
 }
 
@@ -552,11 +583,12 @@ CIrpQueue::HasLastMappingFailed()
     return m_OutOfMapping;
 }
 
-VOID
+ULONG
 NTAPI
-CIrpQueue::PrintQueueStatus()
+CIrpQueue::GetCurrentIrpOffset()
 {
 
+    return m_CurrentOffset;
 }
 
 VOID