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/…
==============================================================================
--- 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/…
==============================================================================
--- 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);
}
}