1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
5  * PURPOSE:         WaveCyclic IRP Audio Pin
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "private.hpp"
10 
11 #ifndef YDEBUG
12 #define NDEBUG
13 #endif
14 
15 #include <debug.h>
16 
17 class CPortPinWaveCyclic : public IPortPinWaveCyclic,
18                            public IServiceSink
19 {
20 public:
21     inline
22     PVOID
23     operator new(
24         size_t Size,
25         POOL_TYPE PoolType,
26         ULONG Tag)
27     {
28         PVOID P = ExAllocatePoolWithTag(PoolType, Size, Tag);
29         if (P)
30             RtlZeroMemory(P, Size);
31         return P;
32     }
33 
34     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
35 
36     STDMETHODIMP_(ULONG) AddRef()
37     {
38         InterlockedIncrement(&m_Ref);
39         return m_Ref;
40     }
41     STDMETHODIMP_(ULONG) Release()
42     {
43         InterlockedDecrement(&m_Ref);
44 
45         if (!m_Ref)
46         {
47             delete this;
48             return 0;
49         }
50         return m_Ref;
51     }
52     IMP_IPortPinWaveCyclic;
53     IMP_IServiceSink;
54     CPortPinWaveCyclic(IUnknown *OuterUnknown){}
55     virtual ~CPortPinWaveCyclic(){}
56 
57 protected:
58 
59     VOID UpdateCommonBuffer(ULONG Position, ULONG MaxTransferCount);
60     VOID UpdateCommonBufferOverlap(ULONG Position, ULONG MaxTransferCount);
61     VOID GeneratePositionEvents(IN ULONGLONG OldOffset, IN ULONGLONG NewOffset);
62 
63     friend NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
64     friend NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
65     friend NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
66     friend NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
67     friend NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA EventData, IN PKSEVENT_ENTRY EventEntry);
68     friend NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
69     friend VOID CALLBACK PinSetStateWorkerRoutine(IN PDEVICE_OBJECT  DeviceObject, IN PVOID  Context);
70 
71     IPortWaveCyclic * m_Port;
72     IPortFilterWaveCyclic * m_Filter;
73     KSPIN_DESCRIPTOR * m_KsPinDescriptor;
74     PMINIPORTWAVECYCLIC m_Miniport;
75     PSERVICEGROUP m_ServiceGroup;
76     PDMACHANNEL m_DmaChannel;
77     PMINIPORTWAVECYCLICSTREAM m_Stream;
78     KSSTATE m_State;
79     PKSDATAFORMAT m_Format;
80     PKSPIN_CONNECT m_ConnectDetails;
81 
82     PVOID m_CommonBuffer;
83     ULONG m_CommonBufferSize;
84     ULONG m_CommonBufferOffset;
85 
86     IIrpQueue * m_IrpQueue;
87 
88     ULONG m_FrameSize;
89     BOOL m_Capture;
90 
91     ULONG m_TotalPackets;
92     ULONG m_StopCount;
93     KSAUDIO_POSITION m_Position;
94     KSALLOCATOR_FRAMING m_AllocatorFraming;
95     PSUBDEVICE_DESCRIPTOR m_Descriptor;
96 
97     KSPIN_LOCK m_EventListLock;
98     LIST_ENTRY m_EventList;
99 
100     KSRESET m_ResetState;
101 
102     ULONG m_Delay;
103 
104     LONG m_Ref;
105 };
106 
107 
108 typedef struct
109 {
110     ULONG bLoopedStreaming;
111     ULONGLONG Position;
112 }LOOPEDSTREAMING_EVENT_CONTEXT, *PLOOPEDSTREAMING_EVENT_CONTEXT;
113 
114 typedef struct
115 {
116     ULONG bLoopedStreaming;
117 }ENDOFSTREAM_EVENT_CONTEXT, *PENDOFSTREAM_EVENT_CONTEXT;
118 
119 
120 
121 NTSTATUS NTAPI PinWaveCyclicState(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
122 NTSTATUS NTAPI PinWaveCyclicDataFormat(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
123 NTSTATUS NTAPI PinWaveCyclicAudioPosition(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
124 NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
125 NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY  EventEntry);
126 NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
127 NTSTATUS NTAPI PinWaveCyclicDRMHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
128 
129 
130 DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
131 DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
132 DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet, PinWaveCyclicDRMHandler);
133 
134 KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
135 {
136     KSEVENT_CONNECTION_ENDOFSTREAM,
137     sizeof(KSEVENTDATA),
138     sizeof(ENDOFSTREAM_EVENT_CONTEXT),
139     PinWaveCyclicAddEndOfStreamEvent,
140     0,
141     0
142 };
143 
144 KSEVENT_ITEM PinWaveCyclicStreamingEventSet =
145 {
146     KSEVENT_LOOPEDSTREAMING_POSITION,
147     sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA),
148     sizeof(LOOPEDSTREAMING_EVENT_CONTEXT),
149     PinWaveCyclicAddLoopedStreamEvent,
150     0,
151     0
152 };
153 
154 
155 KSPROPERTY_SET PinWaveCyclicPropertySet[] =
156 {
157     {
158         &KSPROPSETID_Connection,
159         sizeof(PinWaveCyclicConnectionSet) / sizeof(KSPROPERTY_ITEM),
160         (const KSPROPERTY_ITEM*)&PinWaveCyclicConnectionSet,
161         0,
162         NULL
163     },
164     {
165         &KSPROPSETID_Audio,
166         sizeof(PinWaveCyclicAudioSet) / sizeof(KSPROPERTY_ITEM),
167         (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
168         0,
169         NULL
170     },
171     {
172         &KSPROPSETID_DrmAudioStream,
173         sizeof(PinWaveCyclicDRMSet) / sizeof(KSPROPERTY_ITEM),
174         (const KSPROPERTY_ITEM*)&PinWaveCyclicDRMSet,
175         0,
176         NULL
177     }
178 };
179 
180 KSEVENT_SET PinWaveCyclicEventSet[] =
181 {
182     {
183         &KSEVENTSETID_LoopedStreaming,
184         sizeof(PinWaveCyclicStreamingEventSet) / sizeof(KSEVENT_ITEM),
185         (const KSEVENT_ITEM*)&PinWaveCyclicStreamingEventSet
186     },
187     {
188         &KSEVENTSETID_Connection,
189         sizeof(PinWaveCyclicConnectionEventSet) / sizeof(KSEVENT_ITEM),
190         (const KSEVENT_ITEM*)&PinWaveCyclicConnectionEventSet
191     }
192 };
193 
194 
195 //==================================================================================================================================
196 
197 NTSTATUS
198 NTAPI
199 CPortPinWaveCyclic::QueryInterface(
200     IN  REFIID refiid,
201     OUT PVOID* Output)
202 {
203     DPRINT("IServiceSink_fnQueryInterface entered\n");
204 
205     if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
206         IsEqualGUIDAligned(refiid, IID_IUnknown))
207     {
208         *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
209         PUNKNOWN(*Output)->AddRef();
210         return STATUS_SUCCESS;
211     }
212 
213     if (IsEqualGUIDAligned(refiid, IID_IServiceSink))
214     {
215         *Output = PVOID(PUNKNOWN(PSERVICESINK(this)));
216         PUNKNOWN(*Output)->AddRef();
217         return STATUS_SUCCESS;
218     }
219 
220     return STATUS_UNSUCCESSFUL;
221 }
222 
223 NTSTATUS
224 NTAPI
225 PinWaveCyclicDRMHandler(
226     IN PIRP Irp,
227     IN PKSIDENTIFIER Request,
228     IN OUT PVOID Data)
229 {
230     DPRINT1("PinWaveCyclicDRMHandler\n");
231     ASSERT(0);
232     return STATUS_INVALID_PARAMETER;
233 }
234 
235 
236 NTSTATUS
237 NTAPI
238 PinWaveCyclicAddEndOfStreamEvent(
239     IN PIRP Irp,
240     IN PKSEVENTDATA  EventData,
241     IN PKSEVENT_ENTRY EventEntry)
242 {
243     PENDOFSTREAM_EVENT_CONTEXT Entry;
244     PSUBDEVICE_DESCRIPTOR Descriptor;
245     CPortPinWaveCyclic *Pin;
246 
247     // get sub device descriptor
248     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
249 
250     // sanity check
251     PC_ASSERT(Descriptor);
252     PC_ASSERT(Descriptor->PortPin);
253     PC_ASSERT_IRQL(DISPATCH_LEVEL);
254 
255     // cast to pin impl
256     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
257 
258      // get extra size
259     Entry = (PENDOFSTREAM_EVENT_CONTEXT)(EventEntry + 1);
260 
261     // not a looped event
262     Entry->bLoopedStreaming = FALSE;
263 
264     // insert item
265     (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
266 
267     // done
268     return STATUS_SUCCESS;
269 }
270 
271 NTSTATUS
272 NTAPI
273 PinWaveCyclicAddLoopedStreamEvent(
274     IN PIRP Irp,
275     IN PKSEVENTDATA  EventData,
276     IN PKSEVENT_ENTRY EventEntry)
277 {
278     PLOOPEDSTREAMING_POSITION_EVENT_DATA Data;
279     PLOOPEDSTREAMING_EVENT_CONTEXT Entry;
280     PSUBDEVICE_DESCRIPTOR Descriptor;
281     CPortPinWaveCyclic *Pin;
282 
283     // get sub device descriptor
284     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
285 
286     // sanity check
287     PC_ASSERT(Descriptor);
288     PC_ASSERT(Descriptor->PortPin);
289     PC_ASSERT_IRQL(DISPATCH_LEVEL);
290 
291     // cast to pin impl
292     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
293 
294     // cast to looped event
295     Data = (PLOOPEDSTREAMING_POSITION_EVENT_DATA)EventData;
296 
297     // get extra size
298     Entry = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
299 
300     Entry->bLoopedStreaming = TRUE;
301     Entry->Position = Data->Position;
302 
303     DPRINT1("Added event\n");
304 
305     // insert item
306     (void)ExInterlockedInsertTailList(&Pin->m_EventList, &EventEntry->ListEntry, &Pin->m_EventListLock);
307 
308     // done
309     return STATUS_SUCCESS;
310 }
311 
312 NTSTATUS
313 NTAPI
314 PinWaveCyclicAllocatorFraming(
315     IN PIRP Irp,
316     IN PKSIDENTIFIER Request,
317     IN OUT PVOID Data)
318 {
319     CPortPinWaveCyclic *Pin;
320     PSUBDEVICE_DESCRIPTOR Descriptor;
321 
322     // get sub device descriptor
323     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSEVENT_ITEM_IRP_STORAGE(Irp);
324 
325     // sanity check
326     PC_ASSERT(Descriptor);
327     PC_ASSERT(Descriptor->PortPin);
328     PC_ASSERT_IRQL(DISPATCH_LEVEL);
329 
330     // cast to pin impl
331     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
332 
333 
334     if (Request->Flags & KSPROPERTY_TYPE_GET)
335     {
336         // copy pin framing
337         RtlMoveMemory(Data, &Pin->m_AllocatorFraming, sizeof(KSALLOCATOR_FRAMING));
338 
339         Irp->IoStatus.Information = sizeof(KSALLOCATOR_FRAMING);
340         return STATUS_SUCCESS;
341     }
342 
343     // not supported
344     return STATUS_NOT_SUPPORTED;
345 }
346 
347 NTSTATUS
348 NTAPI
349 PinWaveCyclicAudioPosition(
350     IN PIRP Irp,
351     IN PKSIDENTIFIER Request,
352     IN OUT PVOID Data)
353 {
354     CPortPinWaveCyclic *Pin;
355     PSUBDEVICE_DESCRIPTOR Descriptor;
356     PKSAUDIO_POSITION Position;
357 
358     // get sub device descriptor
359     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
360 
361     // sanity check
362     PC_ASSERT(Descriptor);
363     PC_ASSERT(Descriptor->PortPin);
364     PC_ASSERT_IRQL(DISPATCH_LEVEL);
365 
366     // cast to pin impl
367     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
368 
369     //sanity check
370     PC_ASSERT(Pin->m_Stream);
371 
372     if (Request->Flags & KSPROPERTY_TYPE_GET)
373     {
374         // FIXME non multithreading-safe
375         // copy audio position
376 
377         Position = (PKSAUDIO_POSITION)Data;
378 
379         if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING)
380         {
381             RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
382             DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
383         }
384         else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
385         {
386             Position->PlayOffset = Pin->m_Position.PlayOffset;
387             Position->WriteOffset = (ULONGLONG)Pin->m_IrpQueue->GetCurrentIrpOffset();
388             DPRINT("Play %lu Write %lu\n", Position->PlayOffset, Position->WriteOffset);
389         }
390 
391         Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
392         return STATUS_SUCCESS;
393     }
394 
395     // not supported
396     return STATUS_NOT_SUPPORTED;
397 }
398 
399 typedef struct
400 {
401     CPortPinWaveCyclic *Pin;
402     KSSTATE NewState;
403     PIO_WORKITEM WorkItem;
404     PIRP Irp;
405 
406 }SETPIN_CONTEXT, *PSETPIN_CONTEXT;
407 
408 VOID
409 CALLBACK
410 PinSetStateWorkerRoutine(
411     IN PDEVICE_OBJECT  DeviceObject,
412     IN PVOID  Context)
413 {
414     PSETPIN_CONTEXT PinWorkContext = (PSETPIN_CONTEXT)Context;
415     NTSTATUS Status;
416 
417     // try set stream
418     Status = PinWorkContext->Pin->m_Stream->SetState(PinWorkContext->NewState);
419 
420     DPRINT1("Setting state %u %x\n", PinWorkContext->NewState, Status);
421     if (NT_SUCCESS(Status))
422     {
423         // store new state
424         PinWorkContext->Pin->m_State = PinWorkContext->NewState;
425 
426         if (PinWorkContext->Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && PinWorkContext->Pin->m_State == KSSTATE_STOP)
427         {
428             /* FIXME complete pending irps with successful state */
429             PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
430         }
431         //HACK
432         //PinWorkContext->Pin->m_IrpQueue->CancelBuffers();
433     }
434 
435     // store result
436     PinWorkContext->Irp->IoStatus.Information = sizeof(KSSTATE);
437     PinWorkContext->Irp->IoStatus.Status = Status;
438 
439     // complete irp
440     IoCompleteRequest(PinWorkContext->Irp, IO_NO_INCREMENT);
441 
442     // free work item
443     IoFreeWorkItem(PinWorkContext->WorkItem);
444 
445     // free work context
446     FreeItem(PinWorkContext, TAG_PORTCLASS);
447 
448 }
449 
450 
451 NTSTATUS
452 NTAPI
453 PinWaveCyclicState(
454     IN PIRP Irp,
455     IN PKSIDENTIFIER Request,
456     IN OUT PVOID Data)
457 {
458     NTSTATUS Status = STATUS_UNSUCCESSFUL;
459     CPortPinWaveCyclic *Pin;
460     PSUBDEVICE_DESCRIPTOR Descriptor;
461     PKSSTATE State = (PKSSTATE)Data;
462 
463     // get sub device descriptor
464     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
465 
466     // sanity check
467     PC_ASSERT(Descriptor);
468     PC_ASSERT(Descriptor->PortPin);
469     PC_ASSERT_IRQL(DISPATCH_LEVEL);
470 
471     // cast to pin impl
472     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
473 
474     //sanity check
475     PC_ASSERT(Pin->m_Stream);
476 
477     if (Request->Flags & KSPROPERTY_TYPE_SET)
478     {
479         // try set stream
480         Status = Pin->m_Stream->SetState(*State);
481 
482         DPRINT("Setting state %u %x\n", *State, Status);
483         if (NT_SUCCESS(Status))
484         {
485             // store new state
486             Pin->m_State = *State;
487 
488             if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING && Pin->m_State == KSSTATE_STOP)
489             {
490                 // FIXME
491                 // complete with successful state
492                 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
493                 Pin->m_IrpQueue->CancelBuffers();
494                 Pin->m_Position.PlayOffset = 0;
495                 Pin->m_Position.WriteOffset = 0;
496             }
497             else if (Pin->m_State == KSSTATE_STOP)
498             {
499                 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
500                 Pin->m_IrpQueue->CancelBuffers();
501                 Pin->m_Position.PlayOffset = 0;
502                 Pin->m_Position.WriteOffset = 0;
503             }
504             // store result
505             Irp->IoStatus.Information = sizeof(KSSTATE);
506         }
507         return Status;
508     }
509     else if (Request->Flags & KSPROPERTY_TYPE_GET)
510     {
511         // get current stream state
512         *State = Pin->m_State;
513         // store result
514         Irp->IoStatus.Information = sizeof(KSSTATE);
515 
516         return STATUS_SUCCESS;
517     }
518 
519     // unsupported request
520     return STATUS_NOT_SUPPORTED;
521 }
522 
523 NTSTATUS
524 NTAPI
525 PinWaveCyclicDataFormat(
526     IN PIRP Irp,
527     IN PKSIDENTIFIER Request,
528     IN OUT PVOID Data)
529 {
530     NTSTATUS Status = STATUS_UNSUCCESSFUL;
531     CPortPinWaveCyclic *Pin;
532     PSUBDEVICE_DESCRIPTOR Descriptor;
533     PIO_STACK_LOCATION IoStack;
534 
535     // get current irp stack location
536     IoStack = IoGetCurrentIrpStackLocation(Irp);
537 
538     // get sub device descriptor
539     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
540 
541     // sanity check
542     PC_ASSERT(Descriptor);
543     PC_ASSERT(Descriptor->PortPin);
544 
545     // cast to pin impl
546     Pin = (CPortPinWaveCyclic*)Descriptor->PortPin;
547 
548     //sanity check
549     PC_ASSERT(Pin->m_Stream);
550     PC_ASSERT(Pin->m_Format);
551 
552     if (Request->Flags & KSPROPERTY_TYPE_SET)
553     {
554         // try to change data format
555         PKSDATAFORMAT NewDataFormat, DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
556         ULONG Size = min(Pin->m_Format->FormatSize, DataFormat->FormatSize);
557 
558         if (RtlCompareMemory(DataFormat, Pin->m_Format, Size) == Size)
559         {
560             // format is identical
561             Irp->IoStatus.Information = DataFormat->FormatSize;
562             return STATUS_SUCCESS;
563         }
564 
565         // new change request
566         PC_ASSERT(Pin->m_State != KSSTATE_RUN);
567         // FIXME queue a work item when Irql != PASSIVE_LEVEL
568         PC_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
569 
570         // allocate new data format
571         NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
572         if (!NewDataFormat)
573         {
574             // not enough memory
575             return STATUS_NO_MEMORY;
576         }
577 
578         // copy new data format
579         RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
580 
581         // set new format
582         Status = Pin->m_Stream->SetFormat(NewDataFormat);
583         if (NT_SUCCESS(Status))
584         {
585             // free old format
586             FreeItem(Pin->m_Format, TAG_PORTCLASS);
587 
588             // store new format
589             Pin->m_Format = NewDataFormat;
590             Irp->IoStatus.Information = NewDataFormat->FormatSize;
591 
592 #if 0
593             PC_ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
594             PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO));
595             PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM));
596             PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
597 
598 
599             DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
600                                                                        ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
601                                                                        ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
602 #endif
603 
604         }
605         else
606         {
607             // failed to set format
608             FreeItem(NewDataFormat, TAG_PORTCLASS);
609         }
610 
611 
612         // done
613         return Status;
614     }
615     else if (Request->Flags & KSPROPERTY_TYPE_GET)
616     {
617         // get current data format
618         PC_ASSERT(Pin->m_Format);
619 
620         if (Pin->m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
621         {
622             // buffer too small
623             Irp->IoStatus.Information = Pin->m_Format->FormatSize;
624             return STATUS_MORE_ENTRIES;
625         }
626         // copy data format
627         RtlMoveMemory(Data, Pin->m_Format, Pin->m_Format->FormatSize);
628         // store result size
629         Irp->IoStatus.Information = Pin->m_Format->FormatSize;
630 
631         // done
632         return STATUS_SUCCESS;
633     }
634 
635     // unsupported request
636     return STATUS_NOT_SUPPORTED;
637 }
638 
639 VOID
640 CPortPinWaveCyclic::GeneratePositionEvents(
641     IN ULONGLONG OldOffset,
642     IN ULONGLONG NewOffset)
643 {
644     PLIST_ENTRY Entry;
645     PKSEVENT_ENTRY EventEntry;
646     PLOOPEDSTREAMING_EVENT_CONTEXT Context;
647 
648     // acquire event lock
649     KeAcquireSpinLockAtDpcLevel(&m_EventListLock);
650 
651     // point to first entry
652     Entry = m_EventList.Flink;
653 
654     while(Entry != &m_EventList)
655     {
656         // get event entry
657         EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
658 
659         // get event entry context
660         Context = (PLOOPEDSTREAMING_EVENT_CONTEXT)(EventEntry + 1);
661 
662         if (Context->bLoopedStreaming != FALSE)
663         {
664             if (NewOffset > OldOffset)
665             {
666                 /* buffer progress no overlap */
667                 if (OldOffset < Context->Position && Context->Position <= NewOffset)
668                 {
669                     /* when someone eventually fixes sprintf... */
670                     DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
671                     DPRINT("Context->Position %I64u\n", Context->Position);
672                     DPRINT("NewOffset %I64u\n", NewOffset);
673                     /* generate event */
674                     KsGenerateEvent(EventEntry);
675                 }
676             }
677             else
678             {
679                 /* buffer wrap-arround */
680                 if (OldOffset < Context->Position || NewOffset > Context->Position)
681                 {
682                     /* when someone eventually fixes sprintf... */
683                     DPRINT("Generating event at OldOffset %I64u\n", OldOffset);
684                     DPRINT("Context->Position %I64u\n", Context->Position);
685                     DPRINT("NewOffset %I64u\n", NewOffset);
686                     /* generate event */
687                     KsGenerateEvent(EventEntry);
688                 }
689             }
690         }
691 
692         // move to next entry
693         Entry = Entry->Flink;
694     }
695 
696     // release lock
697     KeReleaseSpinLockFromDpcLevel(&m_EventListLock);
698 }
699 
700 VOID
701 CPortPinWaveCyclic::UpdateCommonBuffer(
702     ULONG Position,
703     ULONG MaxTransferCount)
704 {
705     ULONG BufferLength;
706     ULONG BytesToCopy;
707     ULONG BufferSize;
708     ULONG Gap;
709     PUCHAR Buffer;
710     NTSTATUS Status;
711 
712     BufferLength = Position - m_CommonBufferOffset;
713     BufferLength = min(BufferLength, MaxTransferCount);
714 
715     while(BufferLength)
716     {
717         Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
718         if (!NT_SUCCESS(Status))
719         {
720             Gap = Position - m_CommonBufferOffset;
721             if (Gap > BufferLength)
722             {
723                 // insert silence samples
724                 DPRINT("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength);
725                 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
726 
727                 m_CommonBufferOffset += BufferLength;
728             }
729             break;
730         }
731 
732         BytesToCopy = min(BufferLength, BufferSize);
733 
734         if (m_Capture)
735         {
736             m_DmaChannel->CopyFrom(Buffer, (PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BytesToCopy);
737         }
738         else
739         {
740             m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, Buffer, BytesToCopy);
741         }
742 
743         m_IrpQueue->UpdateMapping(BytesToCopy);
744         m_CommonBufferOffset += BytesToCopy;
745 
746         BufferLength -= BytesToCopy;
747         m_Position.PlayOffset += BytesToCopy;
748 
749         if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
750         {
751             if (m_Position.WriteOffset)
752             {
753                 // normalize position
754                 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
755             }
756         }
757     }
758 }
759 
760 VOID
761 CPortPinWaveCyclic::UpdateCommonBufferOverlap(
762     ULONG Position,
763     ULONG MaxTransferCount)
764 {
765     ULONG BufferLength, Length, Gap;
766     ULONG BytesToCopy;
767     ULONG BufferSize;
768     PUCHAR Buffer;
769     NTSTATUS Status;
770 
771 
772     BufferLength = Gap = m_CommonBufferSize - m_CommonBufferOffset;
773     BufferLength = Length = min(BufferLength, MaxTransferCount);
774     while(BufferLength)
775     {
776         Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
777         if (!NT_SUCCESS(Status))
778         {
779             Gap = m_CommonBufferSize - m_CommonBufferOffset + Position;
780             if (Gap > BufferLength)
781             {
782                 // insert silence samples
783                 DPRINT("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position);
784                 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
785 
786                 m_CommonBufferOffset += BufferLength;
787             }
788             break;
789         }
790 
791         BytesToCopy = min(BufferLength, BufferSize);
792 
793         if (m_Capture)
794         {
795             m_DmaChannel->CopyFrom(Buffer,
796                                              (PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
797                                              BytesToCopy);
798         }
799         else
800         {
801             m_DmaChannel->CopyTo((PUCHAR)m_CommonBuffer + m_CommonBufferOffset,
802                                              Buffer,
803                                              BytesToCopy);
804         }
805 
806         m_IrpQueue->UpdateMapping(BytesToCopy);
807         m_CommonBufferOffset += BytesToCopy;
808         m_Position.PlayOffset += BytesToCopy;
809 
810         BufferLength -=BytesToCopy;
811 
812         if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
813         {
814             if (m_Position.WriteOffset)
815             {
816                 // normalize position
817                 m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
818             }
819         }
820     }
821 
822     if (Gap == Length)
823     {
824         m_CommonBufferOffset = 0;
825 
826         MaxTransferCount -= Length;
827 
828         if (MaxTransferCount)
829         {
830             UpdateCommonBuffer(Position, MaxTransferCount);
831         }
832     }
833 }
834 
835 VOID
836 NTAPI
837 CPortPinWaveCyclic::RequestService()
838 {
839     ULONG Position;
840     ULONGLONG OldOffset, NewOffset;
841 
842     PC_ASSERT_IRQL(DISPATCH_LEVEL);
843 
844     if (m_State == KSSTATE_RUN && m_ResetState == KSRESET_END)
845     {
846         m_Stream->GetPosition(&Position);
847 
848         OldOffset = m_Position.PlayOffset;
849 
850         if (Position < m_CommonBufferOffset)
851         {
852             UpdateCommonBufferOverlap(Position, m_FrameSize);
853         }
854         else if (Position >= m_CommonBufferOffset)
855         {
856             UpdateCommonBuffer(Position, m_FrameSize);
857         }
858 
859         NewOffset = m_Position.PlayOffset;
860 
861         GeneratePositionEvents(OldOffset, NewOffset);
862     }
863 }
864 
865 NTSTATUS
866 NTAPI
867 CPortPinWaveCyclic::NewIrpTarget(
868     OUT struct IIrpTarget **OutTarget,
869     IN PCWSTR Name,
870     IN PUNKNOWN Unknown,
871     IN POOL_TYPE PoolType,
872     IN PDEVICE_OBJECT DeviceObject,
873     IN PIRP Irp,
874     IN KSOBJECT_CREATE *CreateObject)
875 {
876     UNIMPLEMENTED;
877     return STATUS_UNSUCCESSFUL;
878 }
879 
880 NTSTATUS
881 NTAPI
882 CPortPinWaveCyclic::DeviceIoControl(
883     IN PDEVICE_OBJECT DeviceObject,
884     IN PIRP Irp)
885 {
886     PIO_STACK_LOCATION IoStack;
887     PKSPROPERTY Property;
888     UNICODE_STRING GuidString;
889     NTSTATUS Status = STATUS_NOT_SUPPORTED;
890     ULONG Data = 0;
891     KSRESET ResetValue;
892 
893     /* get current irp stack location */
894     IoStack = IoGetCurrentIrpStackLocation(Irp);
895 
896     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
897     {
898         /* handle property with subdevice descriptor */
899         Status = PcHandlePropertyWithTable(Irp,  m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor);
900 
901         if (Status == STATUS_NOT_FOUND)
902         {
903             Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
904 
905             RtlStringFromGUID(Property->Set, &GuidString);
906             DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
907             RtlFreeUnicodeString(&GuidString);
908         }
909     }
910     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
911     {
912         Status = PcHandleEnableEventWithTable(Irp, m_Descriptor);
913     }
914     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
915     {
916         Status = PcHandleDisableEventWithTable(Irp, m_Descriptor);
917     }
918     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
919     {
920         Status = KsAcquireResetValue(Irp, &ResetValue);
921         DPRINT("Status %x Value %u\n", Status, ResetValue);
922         /* check for success */
923         if (NT_SUCCESS(Status))
924         {
925             //determine state of reset request
926             if (ResetValue == KSRESET_BEGIN)
927             {
928                 // start reset process
929                 // incoming read/write requests will be rejected
930                 m_ResetState = KSRESET_BEGIN;
931 
932                 // cancel existing buffers
933                 m_IrpQueue->CancelBuffers();
934             }
935             else if (ResetValue == KSRESET_END)
936             {
937                 // end of reset process
938                 m_ResetState = KSRESET_END;
939             }
940         }
941     }
942     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
943     {
944         /* increment total number of packets */
945         InterlockedIncrement((PLONG)&m_TotalPackets);
946 
947          DPRINT("New Packet Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
948 
949          /* is the device not currently reset */
950          if (m_ResetState == KSRESET_END)
951          {
952              /* add the mapping */
953              Status = m_IrpQueue->AddMapping(Irp, &Data);
954 
955              /* check for success */
956              if (NT_SUCCESS(Status))
957              {
958                 m_Position.WriteOffset += Data;
959                 Status = STATUS_PENDING;
960              }
961          }
962          else
963          {
964              /* reset request is currently in progress */
965              Status = STATUS_DEVICE_NOT_READY;
966              DPRINT1("NotReady\n");
967          }
968     }
969     else
970     {
971         return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
972     }
973 
974     if (Status != STATUS_PENDING)
975     {
976         Irp->IoStatus.Status = Status;
977         IoCompleteRequest(Irp, IO_NO_INCREMENT);
978     }
979 
980     return Status;
981 }
982 
983 NTSTATUS
984 NTAPI
985 CPortPinWaveCyclic::Read(
986     IN PDEVICE_OBJECT DeviceObject,
987     IN PIRP Irp)
988 {
989     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
990 }
991 
992 NTSTATUS
993 NTAPI
994 CPortPinWaveCyclic::Write(
995     IN PDEVICE_OBJECT DeviceObject,
996     IN PIRP Irp)
997 {
998     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
999 }
1000 
1001 NTSTATUS
1002 NTAPI
1003 CPortPinWaveCyclic::Flush(
1004     IN PDEVICE_OBJECT DeviceObject,
1005     IN PIRP Irp)
1006 {
1007     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1008 }
1009 
1010 NTSTATUS
1011 NTAPI
1012 CPortPinWaveCyclic::Close(
1013     IN PDEVICE_OBJECT DeviceObject,
1014     IN PIRP Irp)
1015 {
1016     DPRINT("CPortPinWaveCyclic::Close entered\n");
1017 
1018     PC_ASSERT_IRQL(PASSIVE_LEVEL);
1019 
1020     if (m_Format)
1021     {
1022         // free format
1023         FreeItem(m_Format, TAG_PORTCLASS);
1024 
1025         // format is freed
1026         m_Format = NULL;
1027     }
1028 
1029     if (m_IrpQueue)
1030     {
1031         // cancel remaining irps
1032         m_IrpQueue->CancelBuffers();
1033 
1034         // release irp queue
1035         m_IrpQueue->Release();
1036 
1037         // queue is freed
1038         m_IrpQueue = NULL;
1039     }
1040 
1041     if (m_ServiceGroup)
1042     {
1043         // remove member from service group
1044         m_ServiceGroup->RemoveMember(PSERVICESINK(this));
1045 
1046         // do not release service group, it is released by the miniport object
1047         m_ServiceGroup = NULL;
1048     }
1049 
1050     if (m_Stream)
1051     {
1052         if (m_State != KSSTATE_STOP)
1053         {
1054             // stop stream
1055             NTSTATUS Status = m_Stream->SetState(KSSTATE_STOP);
1056             if (!NT_SUCCESS(Status))
1057             {
1058                 DPRINT("Warning: failed to stop stream with %x\n", Status);
1059                 PC_ASSERT(0);
1060             }
1061         }
1062         // set state to stop
1063         m_State = KSSTATE_STOP;
1064 
1065         DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
1066 
1067         // release stream
1068         m_Stream->Release();
1069 
1070         // stream is now freed
1071         m_Stream = NULL;
1072     }
1073 
1074 
1075     if (m_Filter)
1076     {
1077         // disconnect pin from filter
1078         m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
1079 
1080         // release filter reference
1081         m_Filter->Release();
1082 
1083         // pin is done with filter
1084         m_Filter = NULL;
1085     }
1086 
1087     if (m_Port)
1088     {
1089         // release reference to port driver
1090         m_Port->Release();
1091 
1092         // work is done for port
1093         m_Port = NULL;
1094     }
1095 
1096     Irp->IoStatus.Information = 0;
1097     Irp->IoStatus.Status = STATUS_SUCCESS;
1098     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1099 
1100     delete this;
1101 
1102     return STATUS_SUCCESS;
1103 }
1104 
1105 NTSTATUS
1106 NTAPI
1107 CPortPinWaveCyclic::QuerySecurity(
1108     IN PDEVICE_OBJECT DeviceObject,
1109     IN PIRP Irp)
1110 {
1111     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1112 }
1113 
1114 NTSTATUS
1115 NTAPI
1116 CPortPinWaveCyclic::SetSecurity(
1117     IN PDEVICE_OBJECT DeviceObject,
1118     IN PIRP Irp)
1119 {
1120     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
1121 }
1122 
1123 BOOLEAN
1124 NTAPI
1125 CPortPinWaveCyclic::FastDeviceIoControl(
1126     IN PFILE_OBJECT FileObject,
1127     IN BOOLEAN Wait,
1128     IN PVOID InputBuffer,
1129     IN ULONG InputBufferLength,
1130     OUT PVOID OutputBuffer,
1131     IN ULONG OutputBufferLength,
1132     IN ULONG IoControlCode,
1133     OUT PIO_STATUS_BLOCK StatusBlock,
1134     IN PDEVICE_OBJECT DeviceObject)
1135 {
1136     return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
1137 }
1138 
1139 
1140 BOOLEAN
1141 NTAPI
1142 CPortPinWaveCyclic::FastRead(
1143     IN PFILE_OBJECT FileObject,
1144     IN PLARGE_INTEGER FileOffset,
1145     IN ULONG Length,
1146     IN BOOLEAN Wait,
1147     IN ULONG LockKey,
1148     IN PVOID Buffer,
1149     OUT PIO_STATUS_BLOCK StatusBlock,
1150     IN PDEVICE_OBJECT DeviceObject)
1151 {
1152     return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1153 }
1154 
1155 
1156 BOOLEAN
1157 NTAPI
1158 CPortPinWaveCyclic::FastWrite(
1159     IN PFILE_OBJECT FileObject,
1160     IN PLARGE_INTEGER FileOffset,
1161     IN ULONG Length,
1162     IN BOOLEAN Wait,
1163     IN ULONG LockKey,
1164     IN PVOID Buffer,
1165     OUT PIO_STATUS_BLOCK StatusBlock,
1166     IN PDEVICE_OBJECT DeviceObject)
1167 {
1168     return KsDispatchFastReadFailure(FileObject, FileOffset, Length, Wait, LockKey, Buffer, StatusBlock, DeviceObject);
1169 }
1170 
1171 
1172 NTSTATUS
1173 NTAPI
1174 CPortPinWaveCyclic::Init(
1175     IN PPORTWAVECYCLIC Port,
1176     IN PPORTFILTERWAVECYCLIC Filter,
1177     IN KSPIN_CONNECT * ConnectDetails,
1178     IN KSPIN_DESCRIPTOR * KsPinDescriptor)
1179 {
1180     NTSTATUS Status;
1181     PKSDATAFORMAT DataFormat;
1182     //PDEVICE_OBJECT DeviceObject;
1183     BOOLEAN Capture;
1184     PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
1185     //IDrmAudioStream * DrmAudio = NULL;
1186 
1187     m_KsPinDescriptor = KsPinDescriptor;
1188     m_ConnectDetails = ConnectDetails;
1189     m_Miniport = GetWaveCyclicMiniport(Port);
1190 
1191     //DeviceObject = GetDeviceObject(Port);
1192 
1193     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
1194 
1195     DPRINT("CPortPinWaveCyclic::Init entered Size %u\n", DataFormat->FormatSize);
1196 
1197     Status = NewIrpQueue(&m_IrpQueue);
1198     if (!NT_SUCCESS(Status))
1199         return Status;
1200 
1201     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
1202     {
1203         Capture = FALSE;
1204     }
1205     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
1206     {
1207         Capture = TRUE;
1208     }
1209     else
1210     {
1211         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
1212         DbgBreakPoint();
1213         while(TRUE);
1214     }
1215 
1216 
1217     Status = m_Miniport->NewStream(&m_Stream,
1218                                    NULL,
1219                                    NonPagedPool,
1220                                    ConnectDetails->PinId,
1221                                    Capture,
1222                                    DataFormat,
1223                                    &m_DmaChannel,
1224                                    &m_ServiceGroup);
1225 #if 0
1226     Status = m_Stream->QueryInterface(IID_IDrmAudioStream, (PVOID*)&DrmAudio);
1227     if (NT_SUCCESS(Status))
1228     {
1229         DRMRIGHTS DrmRights;
1230         DPRINT("Got IID_IDrmAudioStream interface %p\n", DrmAudio);
1231 
1232         DrmRights.CopyProtect = FALSE;
1233         DrmRights.Reserved = 0;
1234         DrmRights.DigitalOutputDisable = FALSE;
1235 
1236         Status = DrmAudio->SetContentId(1, &DrmRights);
1237         DPRINT("Status %x\n", Status);
1238     }
1239 #endif
1240 
1241     DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
1242 
1243     if (!NT_SUCCESS(Status))
1244         return Status;
1245 
1246     ISubdevice * Subdevice = NULL;
1247     // get subdevice interface
1248     Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
1249 
1250     if (!NT_SUCCESS(Status))
1251         return Status;
1252 
1253     Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
1254     if (!NT_SUCCESS(Status))
1255     {
1256         // failed to get descriptor
1257         Subdevice->Release();
1258         return Status;
1259     }
1260 
1261     /* initialize event management */
1262     InitializeListHead(&m_EventList);
1263     KeInitializeSpinLock(&m_EventListLock);
1264 
1265     Status = PcCreateSubdeviceDescriptor(&m_Descriptor,
1266                                          SubDeviceDescriptor->InterfaceCount,
1267                                          SubDeviceDescriptor->Interfaces,
1268                                          0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */
1269                                          NULL,
1270                                          sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET),
1271                                          PinWaveCyclicPropertySet,
1272                                          0,
1273                                          0,
1274                                          0,
1275                                          NULL,
1276                                          sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET),
1277                                          PinWaveCyclicEventSet,
1278                                          SubDeviceDescriptor->DeviceDescriptor);
1279 
1280     m_Descriptor->UnknownStream = (PUNKNOWN)m_Stream;
1281     m_Descriptor->UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
1282     m_Descriptor->PortPin = (PVOID)this;
1283     m_Descriptor->EventList = &m_EventList;
1284     m_Descriptor->EventListLock = &m_EventListLock;
1285 
1286     // initialize reset state
1287     m_ResetState = KSRESET_END;
1288 
1289     // release subdevice descriptor
1290     Subdevice->Release();
1291 
1292     // add ourselves to service group
1293     Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
1294     if (!NT_SUCCESS(Status))
1295     {
1296         DPRINT("Failed to add pin to service group\n");
1297         return Status;
1298     }
1299 
1300     m_Stream->SetState(KSSTATE_STOP);
1301     m_State = KSSTATE_STOP;
1302     m_CommonBufferOffset = 0;
1303     m_CommonBufferSize = m_DmaChannel->AllocatedBufferSize();
1304     m_CommonBuffer = m_DmaChannel->SystemAddress();
1305     m_Capture = Capture;
1306     // delay of 10 millisec
1307     m_Delay = Int32x32To64(10, -10000);
1308 
1309     // sanity checks
1310     PC_ASSERT(m_CommonBufferSize);
1311     PC_ASSERT(m_CommonBuffer);
1312 
1313     Status = m_Stream->SetNotificationFreq(10, &m_FrameSize);
1314     PC_ASSERT(NT_SUCCESS(Status));
1315     PC_ASSERT(m_FrameSize);
1316 
1317     DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u CommonBufferSize %lu, CommonBuffer %p\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize, m_CommonBufferSize, m_DmaChannel->SystemAddress());
1318 
1319 
1320     /* set up allocator framing */
1321     m_AllocatorFraming.RequirementsFlags = KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY;
1322     m_AllocatorFraming.PoolType = NonPagedPool;
1323     m_AllocatorFraming.Frames = 8;
1324     m_AllocatorFraming.FileAlignment = FILE_64_BYTE_ALIGNMENT;
1325     m_AllocatorFraming.Reserved = 0;
1326     m_AllocatorFraming.FrameSize = m_FrameSize;
1327 
1328     m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
1329 
1330     Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, m_FrameSize, 0, FALSE);
1331     if (!NT_SUCCESS(Status))
1332     {
1333        m_IrpQueue->Release();
1334        return Status;
1335     }
1336 
1337     m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
1338     if (!m_Format)
1339         return STATUS_INSUFFICIENT_RESOURCES;
1340 
1341     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
1342 
1343     Port->AddRef();
1344     Filter->AddRef();
1345 
1346     m_Port = Port;
1347     m_Filter = Filter;
1348 
1349     return STATUS_SUCCESS;
1350 }
1351 
1352 
1353 ULONG
1354 NTAPI
1355 CPortPinWaveCyclic::GetCompletedPosition()
1356 {
1357     UNIMPLEMENTED;
1358     return 0;
1359 }
1360 
1361 
1362 ULONG
1363 NTAPI
1364 CPortPinWaveCyclic::GetCycleCount()
1365 {
1366     UNIMPLEMENTED;
1367     return 0;
1368 }
1369 
1370 
1371 ULONG
1372 NTAPI
1373 CPortPinWaveCyclic::GetDeviceBufferSize()
1374 {
1375     return m_CommonBufferSize;
1376 }
1377 
1378 
1379 PVOID
1380 NTAPI
1381 CPortPinWaveCyclic::GetIrpStream()
1382 {
1383     return (PVOID)m_IrpQueue;
1384 }
1385 
1386 
1387 PMINIPORT
1388 NTAPI
1389 CPortPinWaveCyclic::GetMiniport()
1390 {
1391     return (PMINIPORT)m_Miniport;
1392 }
1393 
1394 
1395 NTSTATUS
1396 NewPortPinWaveCyclic(
1397     OUT IPortPinWaveCyclic ** OutPin)
1398 {
1399     CPortPinWaveCyclic * This;
1400 
1401     This = new(NonPagedPool, TAG_PORTCLASS)CPortPinWaveCyclic(NULL);
1402     if (!This)
1403         return STATUS_INSUFFICIENT_RESOURCES;
1404 
1405     This->AddRef();
1406 
1407     // store result
1408     *OutPin = (IPortPinWaveCyclic*)This;
1409 
1410     return STATUS_SUCCESS;
1411 }
1412 
1413