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