[ros-diffs] [janderwald] 39674: - Implement writing into cyclic buffer - Implement queuing write requests - Use KeInsertQueueDpc over KeSetTimer in IServiceGroup_fnRequestDelayedService - Playing an irp sound buffer now basically works. However the last sample is always repeated(w/o irp buffer bounds checking playing works normally but bsod occurs due to reading out of bounds)

janderwald at svn.reactos.org janderwald at svn.reactos.org
Thu Feb 19 06:19:09 CET 2009


Author: janderwald
Date: Wed Feb 18 23:19:08 2009
New Revision: 39674

URL: http://svn.reactos.org/svn/reactos?rev=39674&view=rev
Log:
- Implement writing into cyclic buffer
- Implement queuing write requests
- Use KeInsertQueueDpc over KeSetTimer in IServiceGroup_fnRequestDelayedService
- Playing an irp sound buffer now basically works. However the last sample is always repeated(w/o irp buffer bounds checking playing works normally but bsod occurs due to reading out of bounds)

Modified:
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
    trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.c

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c?rev=39674&r1=39673&r2=39674&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] Wed Feb 18 23:19:08 2009
@@ -16,7 +16,26 @@
     KSSTATE State;
     PKSDATAFORMAT Format;
 
+    LIST_ENTRY QueueHead;
+    KSPIN_LOCK QueueLock;
+
+    PVOID CommonBuffer;
+    ULONG CommonBufferSize;
+    ULONG CommonBufferOffset;
+
+    PIRP ActiveIrp;
+    PUCHAR ActiveIrpBuffer;
+    ULONG ActiveIrpBufferSize;
+    ULONG ActiveIrpOffset;
+    ULONG DelayedRequestInProgress;
+
+
 }IPortPinWaveCyclicImpl;
+
+NTSTATUS
+NTAPI
+IPortWaveCyclic_fnProcessNewIrp(
+    IPortPinWaveCyclicImpl * This);
 
 //==================================================================================================================================
 
@@ -81,9 +100,125 @@
 IServiceSink_fnRequestService(
     IServiceSink* iface)
 {
+    ULONG Position;
+    ULONG BufferLength, IrpLength, BytesToCopy;
+    NTSTATUS Status;
+
     IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)CONTAINING_RECORD(iface, IPortPinWaveCyclicImpl, lpVtblServiceSink);
-
-    DPRINT("IServiceSink_fnRequestService entered %p\n", This);
+#if 0
+    if (This->ActiveIrp && This->ActiveIrpOffset >= This->ActiveIrpBufferSize)
+    {
+        if (KeGetCurrentIrql() > DISPATCH_LEVEL)
+        {
+            if (This->DelayedRequestInProgress)
+                return;
+
+            This->ActiveIrp->IoStatus.Information = This->ActiveIrpBufferSize;
+            This->ActiveIrp->IoStatus.Status = STATUS_SUCCESS;
+            This->DelayedRequestInProgress = TRUE;
+            This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L);
+            return;
+        }
+        else
+        {
+            if (This->ActiveIrp)
+            {
+                IoCompleteRequest(This->ActiveIrp, IO_SOUND_INCREMENT);
+            }
+
+            This->ActiveIrp = KsRemoveIrpFromCancelableQueue(&This->QueueHead, &This->QueueLock, KsListEntryTail, KsAcquireAndRemove);
+            if (!This->ActiveIrp)
+            {
+                This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L);
+                return;
+            }
+
+            DPRINT1("processing next irp\n");
+
+            IPortWaveCyclic_fnProcessNewIrp(This);
+            This->DelayedRequestInProgress = FALSE;
+            return;
+        }
+    }
+#endif
+
+    if (!This->ActiveIrp)
+    {
+        if (KeGetCurrentIrql() > DISPATCH_LEVEL)
+        {
+            if (This->DelayedRequestInProgress)
+                return;
+
+            This->DelayedRequestInProgress = TRUE;
+            This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L);
+            return;
+        }
+            This->ActiveIrp = KsRemoveIrpFromCancelableQueue(&This->QueueHead, &This->QueueLock, KsListEntryTail, KsAcquireAndRemove);
+            if (!This->ActiveIrp)
+            {
+                This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, -10000000L);
+                return;
+            }
+
+            IPortWaveCyclic_fnProcessNewIrp(This);
+            This->DelayedRequestInProgress = FALSE;
+            return;
+    }
+
+
+    Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
+    DPRINT1("Position %u BufferSize %u ActiveIrpOffset %u\n", Position, This->CommonBufferSize, This->ActiveIrpOffset);
+
+    if (Position < This->CommonBufferOffset)
+    {
+        BufferLength = This->CommonBufferSize - This->CommonBufferOffset;
+        IrpLength = This->ActiveIrpBufferSize - This->ActiveIrpOffset;
+
+        BytesToCopy = min(BufferLength, IrpLength);
+
+        DPRINT1("Copying %u Remaining %u\n", BytesToCopy, IrpLength);
+
+        if (BytesToCopy)
+        {
+            This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, (PUCHAR)This->ActiveIrpBuffer + This->ActiveIrpOffset, BytesToCopy);
+            This->ActiveIrpOffset += BytesToCopy;
+            This->CommonBufferOffset = 0;
+        }
+        else
+        {
+            This->Stream->lpVtbl->Silence(This->Stream, (PUCHAR)This->CommonBuffer + This->CommonBufferOffset, BytesToCopy);
+        }
+        BufferLength = Position;
+        IrpLength = This->ActiveIrpBufferSize - This->ActiveIrpOffset;
+        BytesToCopy = min(BufferLength, IrpLength);
+
+        DPRINT1("Copying %u Remaining %u\n", BytesToCopy, IrpLength);
+
+        if (BytesToCopy)
+        {
+            This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, (PUCHAR)(PUCHAR)This->CommonBuffer, (PUCHAR)This->ActiveIrpBuffer + This->ActiveIrpOffset, BytesToCopy);
+            This->ActiveIrpOffset += Position;
+            This->CommonBufferOffset = Position;
+        }
+
+    }
+    else if (Position >= This->CommonBufferOffset)
+    {
+        BufferLength = Position - This->CommonBufferOffset;
+        IrpLength = This->ActiveIrpBufferSize - This->ActiveIrpOffset;
+
+        BytesToCopy = min(BufferLength, IrpLength);
+        DPRINT1("Copying %u Remaining %u\n", BytesToCopy, IrpLength);
+
+            This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel,
+                                         (PUCHAR)This->CommonBuffer + This->CommonBufferOffset,
+                                         (PUCHAR)This->ActiveIrpBuffer + This->ActiveIrpOffset,
+                                         BytesToCopy);
+
+        This->ActiveIrpOffset += BytesToCopy;
+        This->CommonBufferOffset = Position;
+    }
+
 }
 
 static IServiceSinkVtbl vt_IServiceSink = 
@@ -173,13 +308,42 @@
 
 NTSTATUS
 NTAPI
+IPortWaveCyclic_fnProcessNewIrp(
+    IPortPinWaveCyclicImpl * This)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKSSTREAM_HEADER Header;
+
+	DPRINT1("ActiveIrp %p\n", This->ActiveIrp);
+
+    IoStack = IoGetCurrentIrpStackLocation(This->ActiveIrp);
+
+    if (IoStack->Parameters.DeviceIoControl.InputBufferLength != sizeof(KSSTREAM_HEADER))
+    {
+        DPRINT1("Irp has unexpected header\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Header = (PKSSTREAM_HEADER)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+    DPRINT1("Header %p Size %u\n", Header, Header->Size);
+
+
+    This->ActiveIrpOffset = 0;
+    This->ActiveIrpBuffer = Header->Data;
+    This->ActiveIrpBufferSize = Header->DataUsed;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
 IPortPinWaveCyclic_HandleKsProperty(
     IN IPortPinWaveCyclic * iface,
     IN PIRP Irp)
 {
     PKSPROPERTY Property;
     NTSTATUS Status;
-    UNICODE_STRING GuidString;
+    UNICODE_STRING GuidString, GuidString2;
     PIO_STACK_LOCATION IoStack;
     IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
 
@@ -209,12 +373,31 @@
                 return STATUS_BUFFER_TOO_SMALL;
             }
 
-            if (Property->Id & KSPROPERTY_TYPE_SET)
+            if (Property->Flags & KSPROPERTY_TYPE_SET)
             {
                 Irp->IoStatus.Information = 0;
                 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
                 if (This->Stream)
                 {
+                    This->CommonBufferOffset = 0;
+                    This->CommonBufferSize = This->DmaChannel->lpVtbl->AllocatedBufferSize(This->DmaChannel);
+                    This->CommonBuffer = This->DmaChannel->lpVtbl->SystemAddress(This->DmaChannel);
+
+                    This->ActiveIrp = KsRemoveIrpFromCancelableQueue(&This->QueueHead, &This->QueueLock, KsListEntryHead, KsAcquireAndRemove);
+                    if (This->ActiveIrp)
+                    {
+                        Status = IPortWaveCyclic_fnProcessNewIrp(This);
+                        DPRINT1("IPortWaveCyclic_fnProcessNewIrp result %x\n", Status);
+                        if (NT_SUCCESS(Status))
+                        {
+                            //FIXME
+                            // verify offset - resume stream
+                            This->DmaChannel->lpVtbl->CopyTo(This->DmaChannel, This->CommonBuffer, This->ActiveIrpBuffer, This->CommonBufferSize);
+                            This->ActiveIrpOffset += This->CommonBufferSize;
+                        }
+                    }
+
+
                     Status = This->Stream->lpVtbl->SetState(This->Stream, *State);
 
                     DPRINT1("Setting state %x\n", Status);
@@ -229,7 +412,7 @@
                 }
                 return Irp->IoStatus.Status;
             }
-            else if (Property->Id & KSPROPERTY_TYPE_GET)
+            else if (Property->Flags & KSPROPERTY_TYPE_GET)
             {
                 *State = This->State;
                 Irp->IoStatus.Information = sizeof(KSSTATE);
@@ -240,7 +423,7 @@
         else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
         {
             PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
-            if (Property->Id & KSPROPERTY_TYPE_SET)
+            if (Property->Flags & KSPROPERTY_TYPE_SET)
             {
                 PKSDATAFORMAT NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
                 if (!NewDataFormat)
@@ -268,7 +451,7 @@
                 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
                 return STATUS_UNSUCCESSFUL;
             }
-            else if (Property->Id & KSPROPERTY_TYPE_GET)
+            else if (Property->Flags & KSPROPERTY_TYPE_GET)
             {
                 PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
                 if (!This->Format)
@@ -291,18 +474,48 @@
                 return STATUS_SUCCESS;
             }
         }
+
     }
     RtlStringFromGUID(&Property->Set, &GuidString);
-
-    DPRINT1("Unhandeled property Set %S Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
+    RtlStringFromGUID(&KSPROPSETID_Connection, &GuidString2);
+    DPRINT1("Unhandeled property Set |%S| |%S|Id %u Flags %x\n", GuidString.Buffer, GuidString2.Buffer, Property->Id, Property->Flags);
     DbgBreakPoint();
     RtlFreeUnicodeString(&GuidString);
+    RtlFreeUnicodeString(&GuidString2);
 
     Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
     Irp->IoStatus.Information = 0;
     return STATUS_NOT_IMPLEMENTED;
 }
 
+NTSTATUS
+NTAPI
+IPortPinWaveCyclic_HandleKsStream(
+    IN IPortPinWaveCyclic * iface,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    DPRINT1("IPortPinWaveCyclic_HandleKsStream entered\n");
+
+    if (!This->Stream)
+    {
+        IoCancelIrp(Irp);
+        Irp->IoStatus.Information = 0;
+        Irp->IoStatus.Status = STATUS_SUCCESS;
+        return Irp->IoStatus.Status;
+    }
+
+    KsAddIrpToCancelableQueue(&This->QueueHead, &This->QueueLock, Irp, KsListEntryTail, NULL);
+    IoMarkIrpPending(Irp);
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_PENDING;
+
+    return STATUS_PENDING;
+}
 
 /*
  * @unimplemented
@@ -316,11 +529,9 @@
 {
     PIO_STACK_LOCATION IoStack;
 
-    UNIMPLEMENTED
-
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    DPRINT1("IPortPinWaveCyclic_fnDeviceIoControl %x %x\n",IoStack->Parameters.DeviceIoControl.IoControlCode,  IOCTL_KS_PROPERTY);
+
     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
     {
        return IPortPinWaveCyclic_HandleKsProperty(iface, Irp);
@@ -342,14 +553,14 @@
     }
     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
     {
-        /// FIXME
-        /// handle reset state
+       return IPortPinWaveCyclic_HandleKsStream(iface, Irp);
     }
     else
     {
         return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
     }
 
+    UNIMPLEMENTED
     return STATUS_UNSUCCESSFUL;
 }
 
@@ -514,6 +725,8 @@
     This->Filter = Filter;
     This->KsPinDescriptor = KsPinDescriptor;
     This->Miniport = GetWaveCyclicMiniport(Port);
+    KeInitializeSpinLock(&This->QueueLock);
+    InitializeListHead(&This->QueueHead);
 
     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
 
@@ -547,6 +760,7 @@
         DPRINT1("Failed to add pin to service group\n");
         return Status;
     }
+    This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
 
     This->State = KSSTATE_STOP;
 

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.c?rev=39674&r1=39673&r2=39674&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/service_group.c [iso-8859-1] Wed Feb 18 23:19:08 2009
@@ -211,7 +211,8 @@
 
     if (This->Initialized)
     {
-        KeSetTimer(&This->Timer, DueTime, &This->Dpc);
+        //KeSetTimer(&This->Timer, DueTime, &This->Dpc);
+        KeInsertQueueDpc(&This->Dpc, NULL, NULL);
         KeClearEvent(&This->DpcEvent);
     }
 }



More information about the Ros-diffs mailing list