[PORTCLS]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 10 Nov 2009 10:01:25 +0000 (10:01 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Tue, 10 Nov 2009 10:01:25 +0000 (10:01 +0000)
- Implement handling of enabling / disabling events
- Implement firing of events when certain position is reached
- Code not yet used as ks needs more work

svn path=/trunk/; revision=44074

reactos/drivers/wdm/audio/backpln/portcls/guids.cpp
reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp
reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
reactos/drivers/wdm/audio/backpln/portcls/private.hpp
reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp

index abc5325..457868d 100644 (file)
@@ -80,6 +80,9 @@ const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {
 const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 const GUID KSPROPTYPESETID_General             = {0x97E99BA0L, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 
+const GUID KSEVENTSETID_LoopedStreaming        = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}};
+const GUID KSEVENTSETID_Connection             = {0x7f4bcbe0L, 0x9ea5, 0x11cf, {0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00}};
+
 const GUID IID_IAllocatorMXF                   = {0xa5f0d62cL, 0xb30f, 0x11d2, {0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
 
 const GUID KSPROPSETID_Audio = {0x45FFAAA0L, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}};
index bf9057b..7aefc88 100644 (file)
@@ -209,6 +209,11 @@ typedef struct
     ULONG FilterPropertySetCount;
     PKSPROPERTY_SET FilterPropertySet;
 
+    ULONG EventSetCount;
+    PKSEVENT_SET EventSet;
+    PLIST_ENTRY EventList;
+    PKSPIN_LOCK EventListLock;
+
     PPCFILTER_DESCRIPTOR DeviceDescriptor;
     KSTOPOLOGY*  Topology;
     LIST_ENTRY SymbolicLinkList;
index 38a6ae9..62a2094 100644 (file)
@@ -41,6 +41,7 @@ protected:
 
     VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
     VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
+    VOID GeneratePositionEvents(IN ULONG OldCommonBufferOffset, IN ULONG NewCommonBufferOffset);
     NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
     NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
 
@@ -49,6 +50,8 @@ protected:
     friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
     friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
     friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+    friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
+    friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
 
     IPortWaveCyclic * m_Port;
     IPortFilterWaveCyclic * m_Filter;
@@ -76,6 +79,9 @@ protected:
     KSALLOCATOR_FRAMING m_AllocatorFraming;
     SUBDEVICE_DESCRIPTOR m_Descriptor;
 
+    KSPIN_LOCK m_EventListLock;
+    LIST_ENTRY m_EventList;
+
     ULONG m_Delay;
 
     LONG m_Ref;
@@ -84,19 +90,49 @@ protected:
 
 typedef struct
 {
-    CPortPinWaveCyclic *Pin;
-    PIO_WORKITEM WorkItem;
-    KSSTATE State;
-}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
+    ULONG bLoopedStreaming;
+    ULONGLONG Position;
+}LOOPEDSTREAMING_EVENT_CONTEXT, *PLOOPEDSTREAMING_EVENT_CONTEXT;
+
+typedef struct
+{
+    ULONG bLoopedStreaming;
+}ENDOFSTREAM_EVENT_CONTEXT, *PENDOFSTREAM_EVENT_CONTEXT;
+
+
 
 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY  EventEntry);
+NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
+
 
 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
 
+KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
+{
+    KSEVENT_CONNECTION_ENDOFSTREAM,
+    sizeof(KSEVENTDATA),
+    sizeof(ENDOFSTREAM_EVENT_CONTEXT),
+    PinWaveCyclicAddEndOfStreamEvent,
+    0,
+    0
+};
+
+KSEVENT_ITEM PinWaveCyclicStreamingEventSet =
+{
+    KSEVENT_LOOPEDSTREAMING_POSITION,
+    sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA),
+    sizeof(LOOPEDSTREAMING_EVENT_CONTEXT),
+    PinWaveCyclicAddLoopedStreamEvent,
+    0,
+    0
+};
+
+
 KSPROPERTY_SET PinWaveCyclicPropertySet[] =
 {
     {
@@ -115,6 +151,21 @@ KSPROPERTY_SET PinWaveCyclicPropertySet[] =
     }
 };
 
+KSEVENT_SET PinWaveCyclicEventSet[] = 
+{
+    {
+        &KSEVENTSETID_LoopedStreaming,
+        sizeof(PinWaveCyclicStreamingEventSet) / sizeof(KSEVENT_ITEM),
+        (const KSEVENT_ITEM*)&PinWaveCyclicStreamingEventSet
+    },
+    {
+        &KSEVENTSETID_Connection,
+        sizeof(PinWaveCyclicConnectionEventSet) / sizeof(KSEVENT_ITEM),
+        (const KSEVENT_ITEM*)&PinWaveCyclicConnectionEventSet
+    }
+};
+
+
 //==================================================================================================================================
 
 NTSTATUS
@@ -143,6 +194,80 @@ CPortPinWaveCyclic::QueryInterface(
     return STATUS_UNSUCCESSFUL;
 }
 
+NTSTATUS
+NTAPI
+PinWaveCyclicAddEndOfStreamEvent(
+    IN PIRP Irp,
+    IN PKSEVENTDATA  EventData,
+    IN PKSEVENT_ENTRY EventEntry)
+{
+    PENDOFSTREAM_EVENT_CONTEXT Entry;
+    PSUBDEVICE_DESCRIPTOR Descriptor;
+    CPortPinWaveCyclic *Pin;
+
+    // get sub device descriptor 
+    Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
+
+    // sanity check 
+    PC_ASSERT(Descriptor);
+    PC_ASSERT(Descriptor->PortPin);
+    PC_ASSERT_IRQL(DISPATCH_LEVEL);
+
+    // cast to pin impl
+    Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
+
+     // get extra size
+    Entry = (PENDOFSTREAM_EVENT_CONTEXT)(EventEntry + 1);
+
+    // not a looped event
+    Entry->bLoopedStreaming = FALSE;
+
+    // insert item
+    (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
+
+    // done
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PinWaveCyclicAddLoopedStreamEvent(
+    IN PIRP Irp,
+    IN PKSEVENTDATA  EventData,
+    IN PKSEVENT_ENTRY EventEntry)
+{
+    PLOOPEDSTREAMING_POSITION_EVENT_DATA Data;
+    PLOOPEDSTREAMING_EVENT_CONTEXT Entry;
+    PSUBDEVICE_DESCRIPTOR Descriptor;
+    CPortPinWaveCyclic *Pin;
+
+    // get sub device descriptor 
+    Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
+
+    // sanity check 
+    PC_ASSERT(Descriptor);
+    PC_ASSERT(Descriptor->PortPin);
+    PC_ASSERT_IRQL(DISPATCH_LEVEL);
+
+    // cast to pin impl
+    Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
+
+    // cast to looped event
+    Data = (PLOOPEDSTREAMING_POSITION_EVENT_DATA)EventData;
+
+    // get extra size
+    Entry = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
+
+    Entry->bLoopedStreaming = TRUE;
+    Entry->Position = Data->Position;
+
+    // insert item
+    (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
+
+    // done
+    return STATUS_SUCCESS;
+}
+
 NTSTATUS
 NTAPI
 PinWaveCyclicAllocatorFraming(
@@ -154,7 +279,7 @@ PinWaveCyclicAllocatorFraming(
     PSUBDEVICE_DESCRIPTOR Descriptor;
 
     // get sub device descriptor 
-    Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
+    Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
 
     // sanity check 
     PC_ASSERT(Descriptor);
@@ -413,6 +538,58 @@ PinWaveCyclicDataFormat(
     return STATUS_NOT_SUPPORTED;
 }
 
+VOID
+CPortPinWaveCyclic::GeneratePositionEvents(
+    IN ULONG OldCommonBufferOffset,
+    IN ULONG NewCommonBufferOffset)
+{
+    PLIST_ENTRY Entry;
+    PKSEVENT_ENTRY EventEntry;
+    PLOOPEDSTREAMING_EVENT_CONTEXT Context;
+
+    // acquire event lock
+    KeAcquireSpinLockAtDpcLevel(&m_EventListLock);
+
+    // point to first entry
+    Entry = m_EventList.Flink;
+
+    while(Entry != &m_EventList)
+    {
+        // get event entry
+        EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
+
+        // get event entry context
+        Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
+
+        if (Context->bLoopedStreaming == TRUE)
+        {
+            if (NewCommonBufferOffset > OldCommonBufferOffset)
+            {
+                /* buffer progress no overlap */
+                if (OldCommonBufferOffset < Context->Position && Context->Position <= NewCommonBufferOffset)
+                {
+                    /* generate event */
+                    KsGenerateEvent(EventEntry);
+                }
+            }
+            else
+            {
+                /* buffer wrap-arround */
+                if (OldCommonBufferOffset < Context->Position || NewCommonBufferOffset > Context->Position)
+                {
+                    /* generate event */
+                    KsGenerateEvent(EventEntry);
+                }
+            }
+        }
+
+        // move to next entry
+        Entry = Entry->Flink;
+    }
+
+    // release lock
+    KeReleaseSpinLockFromDpcLevel(&m_EventListLock);
+}
 
 VOID
 CPortPinWaveCyclic::UpdateCommonBuffer(
@@ -516,6 +693,7 @@ CPortPinWaveCyclic::RequestService()
     NTSTATUS Status;
     PUCHAR Buffer;
     ULONG BufferSize;
+    ULONG OldCommonBufferOffset;
 
     PC_ASSERT_IRQL(DISPATCH_LEVEL);
 
@@ -528,6 +706,8 @@ CPortPinWaveCyclic::RequestService()
     Status = m_Stream->GetPosition(&Position);
     DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
 
+    OldCommonBufferOffset = m_CommonBufferOffset;
+
     if (Position < m_CommonBufferOffset)
     {
         UpdateCommonBufferOverlap(Position, m_FrameSize);
@@ -536,6 +716,8 @@ CPortPinWaveCyclic::RequestService()
     {
         UpdateCommonBuffer(Position, m_FrameSize);
     }
+
+    GeneratePositionEvents(OldCommonBufferOffset, m_CommonBufferOffset);
 }
 
 NTSTATUS
@@ -569,16 +751,6 @@ CPortPinWaveCyclic::HandleKsProperty(
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
-    {
-        DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
-        
-        Irp->IoStatus.Status = STATUS_SUCCESS;
-
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_SUCCESS;
-    }
-
     Status = PcHandlePropertyWithTable(Irp,  m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
 
     if (Status == STATUS_NOT_FOUND)
@@ -629,6 +801,7 @@ CPortPinWaveCyclic::DeviceIoControl(
     IN PIRP Irp)
 {
     PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status = STATUS_NOT_SUPPORTED;
 
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
@@ -639,13 +812,11 @@ CPortPinWaveCyclic::DeviceIoControl(
     }
     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
     {
-        /// FIXME
-        /// handle enable event
+        Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
     }
     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
     {
-        /// FIXME
-        /// handle disable event
+        Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
     }
     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
     {
@@ -661,13 +832,13 @@ CPortPinWaveCyclic::DeviceIoControl(
         return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
     }
 
-    UNIMPLEMENTED
-
-    Irp->IoStatus.Information = 0;
-    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    if (Status != STATUS_PENDING)
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
 
-    return STATUS_UNSUCCESSFUL;
+    return Status;
 }
 
 NTSTATUS
@@ -912,8 +1083,8 @@ CPortPinWaveCyclic::Init(
     }
 #endif
 
-    DPRINT("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
-    DPRINT("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize);
+    DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
+    DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize);
 
     if (!NT_SUCCESS(Status))
         return Status;
@@ -933,6 +1104,10 @@ CPortPinWaveCyclic::Init(
         return Status;
     }
 
+    /* initialize event management */
+    InitializeListHead(&m_EventList);
+    KeInitializeSpinLock(&m_EventListLock);
+
     /* set up subdevice descriptor */
     RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
     m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
@@ -941,6 +1116,10 @@ CPortPinWaveCyclic::Init(
     m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
     m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
     m_Descriptor.PortPin = (PVOID)this;
+    m_Descriptor.EventSetCount = sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET);
+    m_Descriptor.EventSet = PinWaveCyclicEventSet;
+    m_Descriptor.EventList = &m_EventList;
+    m_Descriptor.EventListLock = &m_EventListLock;
 
     // release subdevice descriptor
     Subdevice->Release();
@@ -993,12 +1172,6 @@ CPortPinWaveCyclic::Init(
 
     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
 
-    PKSDATAFORMAT_WAVEFORMATEX Wave = (PKSDATAFORMAT_WAVEFORMATEX)m_Format;
-
-       DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", Wave->WaveFormatEx.wBitsPerSample, Wave->WaveFormatEx.nSamplesPerSec, Wave->WaveFormatEx.nChannels, Wave->WaveFormatEx.wFormatTag, m_FrameSize);
-
-
-
     Port->AddRef();
     Filter->AddRef();
 
index 1df2b4b..45e6092 100644 (file)
@@ -316,6 +316,20 @@ PcHandlePropertyWithTable(
     IN PKSPROPERTY_SET PropertySet,
     IN PSUBDEVICE_DESCRIPTOR Descriptor);
 
+NTSTATUS
+NTAPI
+PcHandleEnableEventWithTable(
+    IN PIRP Irp,
+    IN PSUBDEVICE_DESCRIPTOR Descriptor);
+
+NTSTATUS
+NTAPI
+PcHandleDisableEventWithTable(
+    IN PIRP Irp,
+    IN PSUBDEVICE_DESCRIPTOR Descriptor);
+
+
+
 #define DEFINE_KSPROPERTY_CONNECTIONSET(PinSet,\
     PropStateHandler, PropDataFormatHandler, PropAllocatorFraming)\
 DEFINE_KSPROPERTY_TABLE(PinSet) {\
index 56c2597..21e2bf1 100644 (file)
@@ -59,6 +59,34 @@ KsoGetIrpTargetFromIrp(
     return (IIrpTarget*)CreateItem->Context;
 }
 
+NTSTATUS
+NTAPI
+PcHandleEnableEventWithTable(
+    IN PIRP Irp,
+    IN PSUBDEVICE_DESCRIPTOR Descriptor)
+{
+    // store descriptor
+    KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
+
+    // FIXME seh probing
+    return KsEnableEvent(Irp, Descriptor->EventSetCount, Descriptor->EventSet, NULL, KSEVENTS_NONE, NULL);
+}
+
+NTSTATUS
+NTAPI
+PcHandleDisableEventWithTable(
+    IN PIRP Irp,
+    IN PSUBDEVICE_DESCRIPTOR Descriptor)
+{
+    // store descriptor
+    KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
+
+    // FIXME seh probing
+
+    return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock);
+}
+
+
 NTSTATUS
 NTAPI
 PcHandlePropertyWithTable(