diff --git a/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp b/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp index abc5325cf63..457868d2c62 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/guids.cpp @@ -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}}; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp b/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp index bf9057b3fb2..7aefc882ee4 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp @@ -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; diff --git a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp index 38a6ae91ff5..62a2094bba8 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp @@ -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 + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - 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(); diff --git a/reactos/drivers/wdm/audio/backpln/portcls/private.hpp b/reactos/drivers/wdm/audio/backpln/portcls/private.hpp index 1df2b4b9540..45e6092e6e3 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/private.hpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/private.hpp @@ -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) {\ diff --git a/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp b/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp index 56c25973745..21e2bf1ec2d 100644 --- a/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp +++ b/reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp @@ -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(