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